Fork me on GitHub
#clojurescript
<
2018-04-09
>
cjmurphy01:04:03

Does anyone know of an example of a simple dropdown component I can use that has no internal state, so is a controlled component. Or just some text somewhere of what you need to do to built one from a dom/select that is comprised of several dom/option.

cjmurphy01:04:51

Having an onChange, even one that does nothing but print, seems to turn the component I'm looking at into something that changes how it looks in response to my user actions - something that has internal state.

darwin01:04:07

@cjmurphy have you looked at the combobox in the closure library?

cjmurphy01:04:00

Err no. What a good idea. Thanks @darwin

cjmurphy01:04:34

It seems to have a getModel and setModel methods. Seems to have its own internal state.

darwin01:04:06

what is the problem? you can reset it externally

cjmurphy02:04:13

I just think that if the user changes the selection and it changes itself, then some code also changes the external model that is really supposed to be the state for which item is selected, that things can be confusing. Would be good to have something that only changes when you feed it props.

cjmurphy02:04:40

If I could guarantee that the external change overwrites the internal change then I suppose that would be okay. But can I guarantee that?

cjmurphy02:04:14

Some kind of 'post-change' rather than 'pre' or 'on' change would I suppose guarantee that.

darwin02:04:39

I’m not very familiar with goog.ui, but I would guess there will be a way how to make UI components “disabled” or “read-only”

darwin02:04:02

to prevent changes by user

cjmurphy02:04:41

They (disabled, read-only) might alter the look. But yes it seems listen would be a reasonable way to go. On response to listen my external code would set which item should be selected, on all controls that are responding to that particular bit of external state, including the control that emitted the event.

cjmurphy02:04:39

The actual problem with this dropdown (simple html) I'm dealing with boils down to sometimes ignoring external state changes that are coming in. They always come in because I'm printing them, just are sometimes ignored. I guess that's a part of its uncontrolled behaviour...

cjmurphy06:04:53

In the end I fixed the problem by having the 'component' be created in sablano hiccup and turned into dom using the sablano html function every time there's a React change that comes through. I guess the fact that the component is presented as a faits accompli every time means there's no possibility for an onChange event to be doing weird things.

dehli15:04:02

is is possible to write a clojurescript macro that references a clojurescript function in another namespace?

dehli15:04:00

When I try to do that, it’s claiming it can’t find the other function that I require at the top. I’m guessing it’s b/c it’s a Clojurescript dependency and not a Clojure one

mfikes15:04:28

@dehli Right. In that case, the ClojureScript code that :require-macros on your macro namespace would have to :require that other namespace.

mfikes15:04:47

There is a cleaner solution, though @dehli where you can instead write a ClojureScript namespace that then :require-macros on itself, and then in your client namespace, simply :require that namespace.

dehli15:04:39

Cool. Thanks a lot! I’ll give that a look

mfikes15:04:46

Cool, ask if you encounter difficulty. In that new ClojureScript, you can then require the “other” namespace. The pattern is that you end up *.cljs / *.clj pairs, where the *.cljs can :require-macros on itself and also require any other ClojureScript namespaces that the *.clj macros will expand to use.

dehli15:04:03

Thanks, that makes a lot of sense 🙂

ajs15:04:04

Under what conditions does cljsbuild or figwheel actually pay attention to .clj files? I though they were ignored as that appears to be the case usually, but I just got a figwheel error for a clj file during its recompile so now I'm excluding the src/clj dir from the cljsbuild profile.

mfikes15:04:23

@ajs Usually a .clj file would only be compiled if some ClojureScript namespace :require-macros on it

ajs15:04:29

I thought so too, but doesn't appear to be the case in my scenario. Oh well I guess explicitly telling it which src dirs is not unwise

mfikes15:04:54

@ajs Do you perhaps have a *.cljc file instead of a *.clj?

ajs15:04:29

I do have cljc files also, but the error was with a clj file that is not required from them

ajs15:04:50

Maybe cljsbuild got confused when handling cljc files

mfikes15:04:55

Interesting… well, hopefully the compiler stacktrace gives a clue as to why it got compiled

ajs15:04:32

I will see if it's still in my terminal session

dehli15:04:29

Do all functions have to be fully qualified in the macros? I’m getting the following:

WARNING: Use of undeclared Var common.lambda.core-async/<!
But at the top of that cljs file I have
(:require [cljs.core.async :refer [<!]])
Edit: This started working for some reason. Not sure what happened but disregard this question 🙂

john16:04:11

for module code-splitting, most of the docs mention using {:entries '#{foo.core} ... where foo.core is in a quoted set. With the latest cljs.main though, I'm trying to provide the compiler options as a co.edn file, but the EdnReader is choking on it with: Map literal must contain an even number of forms

dehli16:04:48

what’s your co.edn look like?

john16:04:50

if I simply remove the quotes, things compile fine

john16:04:28

But the project has gotten to such a size where the modules are no longer loading properly and I'm wondering if these entry declarations are to blame.

nijk16:04:04

When compiling a project with :optimizations :advanced I don’t seem to have the process.env.NODE_ENV as a javascript global. It is defined when using :optimizations :none Does anyone know what might be happening here?

john16:04:22

@nick828 I don't use node that much atm, but I think I've heard mention that :advanced may not be necessary for node

justinlee16:04:28

presumably closure is munging the env/NODE_ENV symbols. you’ll either need to add some externs for them or call out to cljs-oops or google’s functions.

justinlee16:04:16

as john pointed out, advanced optimizations are mostly intended for size, not speed, so often there’s really no point in compiling in advanced mode for node (though perhaps for aws lambda it is worth it--unclear to me)

nijk16:04:06

Thanks, the need for this variable is to do runtime environment checking in React’s PropTypes to eliminate dead code - I’m not sure that ClosureCompiler is munging the variable names as a search in the JS for “production” yields nothing, suggesting the variable is not even compiled

justinlee16:04:18

but I think that’s the point--it would be compiled with a different name

nijk16:04:43

sure, but the string value would still be the same would it not? e.g. var mungedProcess = { mungedEnv: { mungedNODE_ENV: "production" } }

nijk16:04:49

Would the string value "production" change?

justinlee16:04:13

hm perhaps it getting eliminated. i actually don’t know if externs definitions affect DCE

john16:04:51

Externs make closure aware of foreign names, so your code calling foreign names don't get munged.

nijk16:04:31

@john that doesn’t explain why the string value of the munged variable does not exist - it’s omission suggests that it’s not being included in the compiled version of the JS at all

john16:04:46

If the above js lives inside the code that closure is minifying, the above js may get eliminated. If NODE_ENV is referring to a cljs value, it likely lives in the non-foreign, closure affected code.

john16:04:34

@nick828 where does the above js line come from?

nijk16:04:28

Ah, ok that sounds more like it. The above code is just an example of what I meant by the string value of "production" in the context of munged closure compiled code

nijk16:04:19

The code I’m hoping to include on the page is this:

var process = { env: { NODE_ENV: "production" } }
Which should be included by using the compiler on it’s default setting of :process-shim: https://clojurescript.org/reference/compiler-options#process-shim

john16:04:26

You mentioned this was for DCE. Why are you doing this for DCE?

nijk16:04:49

I’m sorry I don’t know what you mean by DCE

nijk16:04:52

Ah, just googled it

john16:04:02

dead code elimination. You said "the need for this variable is ... to eliminate dead code"

nijk16:04:37

Yeah, so I’m looking to upgrade a cljsjs package called react-popper as it’s something we use on my current project. The build process in the React dependency includes a babel plugin called transform-react-remove-prop-types that deals with the DCE by wrapping the React component’s propTypes definitions with a conditional to check the NODE_ENV:

Popper.propTypes = process.env.NODE_ENV !== "production" ? { ...propTypeDefinitions } : {};

nijk16:04:02

Unfortunately I don’t have much control over the ReactPopper dependency to remove the babel plugin, so my remaining option is to make process available as a global var

john16:04:44

hmm so NODE_ENV is not a cljs val

justinlee16:04:45

Doesn’t react-popper come with a prebuilt minified production release?

nijk16:04:12

It does once built, but that also includes the same conditional

justinlee16:04:44

also: when you say that you want to include that code, you don’t mean that you wrote that code and it’s being eliminated, you mean that the :process-shim compiler feature doesn’t appear to be setting it?

john16:04:47

Yeah, this area is beyond my experience. But some ideas: bringing it in as a foreign-lib might prevent munging. Also, there's something called preprocessing: https://clojurescript.org/reference/javascript-library-preprocessing

nijk16:04:20

@lee.justin.m I mean that :process-shim does not appear to be adding process.env.NODE_ENV to the closure complied js when :advanced is turned on

justinlee16:04:54

right okay. i was just confused earlier because I thought you had actually written a line of javascript somewhere and it was getting eliminated

nijk16:04:26

ah I see, sorry for the confusion

justinlee16:04:30

right so in my release builds I see a line xa("process.env.NODE_ENV","production")

john16:04:56

@lee.justin.m do you advanced compile for node?

justinlee16:04:11

not for node, but :process-shim is on by default

nijk16:04:52

I find it interesting that you guys refer to npm provided dependencies as ‘node’

justinlee16:04:27

@nick828 we’re talking about the target. people tend to talk about targeting the browser or target node

justinlee16:04:36

npm dependencies can be used on either

nijk16:04:40

that makes more sense

nijk16:04:54

Just to clarify, my target is the browser

justinlee16:04:59

what version of the compiler are you using? you should see the process shim in your release build

richiardiandrea16:04:16

oh co.edn is a good name 😄

🙂 4
john16:04:43

I'm about to build a repro from scratch to suss out these issues

nijk16:04:59

@lee.justin.m What’s the best way to check?

nijk16:04:05

I’m not sure tbh

john16:04:30

aka, what version of clojurescript, in your deps

nijk16:04:47

[org.clojure/clojurescript “1.10.238”

nijk16:04:41

@lee.justin.m ^ does that help?

justinlee16:04:17

sorry I don’t know what’s going on. I might try a fresh project with the same dependencies and see if that works. Then add your code back in. It is hard to tell why you’re not getting what you expect.

nijk17:04:16

@lee.justin.m ok, thanks - can you just tell me what xa is in your previous code example? xa("process.env.NODE_ENV","production")

nijk17:04:44

Oh hang on, it’s probably a munged console.log right?

justinlee17:04:17

it is presumably the munged call to goog.define

👍 4
nijk17:04:41

Thanks all

thheller17:04:43

you can set :pseudo-names true to find out

nijk17:04:23

@thheller Yeah I noticed that compiler option too, but I still didn’t see process on the window object

thheller17:04:24

I meant to find out what xa is. it doesn't have any impact on process. I guess that xa actually is goog.exportSymbol as goog-define does not remain in :advanced

nijk17:04:47

oh I see, it was justinlee’s code snippet so I haven’t come across that in my code yet

justinlee17:04:19

oh interesting. you know i was accidentally grepping a feb 29 release build, which was made with an older compiler. my newer releases don’t have “production” in them

thheller17:04:01

this works differently in shadow-cljs these days. creating a global process proved problematic in a few cases

justinlee17:04:14

@thheller what’s the difference between creating a release from the command line and creating a “release snapshot” from the repl using (shadow.cljs.devtools.api/release-snapshot :app {})? because i was grepping a snapshot earlier and now i’m grepping the main.js placed in public/js. I downgraded to cljs 1.9.946 and shadow 2.2.6 but I still don’t see it

thheller17:04:05

you are grepping what? there is no process.env.NODE_ENV in shadow-cljs

thheller17:04:49

it doesn't actually create release builds

justinlee17:04:10

@nick828 ignore what i was saying earlier. i am using shadow-cljs, which operates differently and I was also grepping the wrong thing

john19:04:46

I get Cannot read property 'EvaluateCodeEvent' of undefined and Cannot read property 'RequestSuccessEvent' of undefined, which appears to be a property hanging off of goog.module.ModuleLoader

john19:04:36

Just added a little readme in there describing how to launch

wjh22:04:40

Hey - I'm currently trying to use npm-deps to require a NPM scoped package, but I'm having some issues. I have this:

(ns front.core
    (:require 
      [reagent.core :as reagent :refer [atom]]
      ["@blueprintjs/core" :as bpc]))

wjh22:04:27

which gives me this error:

Assert failed: cljs.analyzer/foreign-dep? expected symbol got "@blueprintjs/core"
(symbol? dep)

wjh22:04:37

but as far as I know, I should be able to require a string?

cjmurphy23:04:50

Can anyone (JavaScript ppl) help me with js/old in cljs code. I'm getting 'old is not defined' and a stack trace in the browser console. But perhaps it used to be accepted and have meaning in an earlier form of clojurescript? Or there's something I should be doing to this code so that js/old is accepted.

darwin23:04:06

@cjmurphy don’t you have :optimizations :advanced enabled? is old really a global variable in browser context?

cjmurphy23:04:36

I would think that it is not a global variable in browser context, so not like js/parseInt, which gets accepted. But in this code I'm trying to get to compile it certainly looks like it was accepted at some stage. I would think that I don't have :optimizations :advanced enabled. I would hope that written code would be accepted regardless of any setting for :optimizations, or perhaps I misunderstand.

cjmurphy23:04:46

Is there a list of js/XXX things somewhere?

darwin23:04:10

wait, js is just a pseudo namespace to directly access javascript browser context, e.g. you can call javascript functions on window object using it

cjmurphy23:04:28

Maybe I'm running code that will work in production, but won't work in development where :optimizations :advanced is not set.

cjmurphy23:04:04

It is a funny thing to ask a browser if it is old, and expect this question to be asked for many years into the future. Perhaps that's why browsers are deciding not to accept it.

cjmurphy23:04:54

Hmm - I guess it could be defined sensibly.