Fork me on GitHub

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.


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.


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


Err no. What a good idea. Thanks @darwin


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


what is the problem? you can reset it externally


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.


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


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


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”


to prevent changes by user


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.


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...


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.


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


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


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


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.


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


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.


Thanks, that makes a lot of sense 🙂


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.


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


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


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


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


Maybe cljsbuild got confused when handling cljc files


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


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


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 🙂


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


what’s your co.edn look like?


if I simply remove the quotes, things compile fine


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.


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?


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


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.


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)


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


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


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


Would the string value "production" change?


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


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


@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


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.


@nick828 where does the above js line come from?


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


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:


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


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


Ah, just googled it


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


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 } : {};


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


hmm so NODE_ENV is not a cljs val


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


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


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?


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:


@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


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


ah I see, sorry for the confusion


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


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


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


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


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


npm dependencies can be used on either


that makes more sense


Just to clarify, my target is the browser


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


oh co.edn is a good name 😄

🙂 4

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


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


I’m not sure tbh


aka, what version of clojurescript, in your deps


[org.clojure/clojurescript “1.10.238”


@lee.justin.m ^ does that help?


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.


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


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


it is presumably the munged call to goog.define

👍 4

Thanks all


you can set :pseudo-names true to find out


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


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


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


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


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


@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


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


it doesn't actually create release builds


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


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


Just added a little readme in there describing how to launch


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
      [reagent.core :as reagent :refer [atom]]
      ["@blueprintjs/core" :as bpc]))


which gives me this error:

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


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


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.


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


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.


Is there a list of js/XXX things somewhere?


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


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


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.


Hmm - I guess it could be defined sensibly.