This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-10-21
Channels
- # 100-days-of-code (5)
- # announcements (6)
- # beginners (92)
- # cider (39)
- # cljdoc (35)
- # cljsrn (1)
- # clojure (187)
- # clojure-sanfrancisco (2)
- # clojure-spec (26)
- # clojure-sweden (2)
- # clojure-uk (1)
- # clojurescript (27)
- # cursive (19)
- # datascript (3)
- # datomic (19)
- # defnpodcast (1)
- # emacs (11)
- # fulcro (71)
- # incanter (1)
- # lein-figwheel (4)
- # lumo (10)
- # off-topic (19)
- # planck (5)
- # reagent (49)
- # reitit (2)
- # shadow-cljs (25)
- # spacemacs (1)
- # sql (1)
- # unrepl (4)
- # yada (4)
we usually use the fn version of it, I personally usually write like this:
(dom/div {:ref #(gobj/set this "refName" %)})
[goog.object :as gobj]
to require gobj
then you cna get it with (gobj/get this "refName")
in the places you need it
be careful with re-creating the :ref
fn in each render. that will call the ref fn twice per render. one with nil
and once with the node
really? isn't this the React recommended way of doing it?
humm, gotcha
@U066U8JQJ ahthanks! why do you use goog.object there? this
is not a clojure object/map?
this
is the react componet, so a JS object
And the :initLocalState
is your constructor, so you can even put them in component-local state with:
:initLocalState (fn []
{:save-ref (fn [r] (gobj/set...))})
also, quick question: how non-idiomatic would it be to have data in the global state that doesn’t directly control the UI? By this I mean: for some feature I need to store whether an input is focussed or not (to display a toolbar when focussed), but the focus state of the input wouldn’t be controlled by the data.
@hmaurer why you cant store in the regular app state?
can you clarify what you mean by global state that doesn’t directly control the UI
?
that was poorly phrased. What i mean is that usually you would want your UI to be a pure function of state, so that you can time-travel, etc. In this case I would have a piece of data in the state indicating whether the input is focussed or not, but the focus state of the input would not depend on the state
you can still use the app state for it, take load markers for example, they are not part of the component UI directly, you can create a custom marker for you in the app state root, and make any component look at it
for example, lets say you have an input with this:
(dom/input {:onFocus #(fp/transact! this [`(set-focus-marker {:focus true})])
:onBlur #(fp/transact! this [`(set-focus-marker {:focus false})])})
then you get the mutation:
(fm/defmutation set-focus-marker [{:keys [focus]}]
(action [{:keys [state]}]
(swap! state assoc :input-in-focus focus)))
now, if you need to know about this in a component, do a root query for it:
[:something/id :bla :other-data [:input-in-focus '_]]
then you will have :input-in-focus
available in the props
use component local state, refs, and lifecycle for that…just normal react stuff…I guess you could “track” that in app state
In some of my apps I’ve need to deal with refs on a heavy level (e.g. drag and drop)…I’ve done things like created global atoms to store current refs by component ID
not app state, though, because the DOM elements are not serializable for app state…and will break features
but either way…DOM “state” like focus doesn’t belong in app state IMO, because it isn’t enforceable by react, so it has no real meaning for it to be in the state that is supposed to be a pure representation of UI reality.
@tony.kay thanks for the lengthy reply! My reson for storing focus is two-fold: (1) I want to display a toolbar under the input when it is focussed (2) I need to be able to insert “special characters” in my input when pressing buttons in the toolbar (greek letters etc). The way I did this in the past using a vanilla react component was to store the current selection range in the react component’s state. Then, when inserting a special character, I would update the input’s value (which was controlled by the state) and AFTER the state update completed (in a setState callback) I would set the selection range to the appropriate value on the input (i.e. cursor position + 1 for the new character) and focus it
Sometimes the low-level DOM stuff is messy…React cannot control certain things, and doing low-level c-local crap is all you can do…
Fulcro relies on React…so Fulcro really can’t do the DOM stuff any “better”…it isn’t doing any DOM stuff itself 🙂
There are literally 2-3 react calls in the entire source code of Fulcro…render and createElement
fair 🙂 Speaking of, is it easy to use existing react component librairies with Fulcro? i.e. BlueprintJS
I’m trying to get the new pessimistic mutations working
(defmutation login [params]
(action [{:keys [state]}]
(auth/remove-token)
(swap! state dissoc ::user/current-user)
(log/info "Attempting to login"))
(ok-action [{:keys [ref state] :as env}]
(log/info "Authentication Successful")
(util/spy :pp (get-in @state (conj ref ::pm/mutation-response))))
(error-action [env]
(log/error "Authentication Unsuccessful"))
(remote [{:keys [ast state] :as env}]
(pm/pessimistic-mutation env)))
but the ok-action
is being triggered even though the server is throwing an exception
(get-in (clojure.core/deref state) (conj ref :fulcro.incubator.pessimistic-mutations/mutation-response)) => {:fulcro.client.primitives/ref
[:ucv.ui.root.signon/form-control :singleton],
:fulcro.incubator.pessimistic-mutations/status :hard-error,
:fulcro.incubator.pessimistic-mutations/error-marker :Sad-face,
:fulcro.incubator.pessimistic-mutations/low-level-error
{:type "class clojure.lang.ExceptionInfo",
:message "Incorrect email or password",
:data {}}}
[fulcrologic/fulcro-incubator "0.0.3-SNAPSHOT"]
[fulcrologic/fulcro “2.6.9”]
ah i see
0.0.3 didn’t work either
@currentoor you’re using the new pessimistic-mutations namespace, right? Not the ones in db-helpers