is there a way to use componentDidCatch
with Helix? (aka error boundaries: https://reactjs.org/docs/error-boundaries.html)
there is, you can use defcomponent
which defines a class component that you can implement componentDidCatch
and other lifecycle methods
it's very under-documented tho
One of the only things I miss about reagent/re-frame when using helix is the ability to arbitrarily dispatch an event from the REPL? Has anyone solved this in a novel way? I feel like this is a limitation of React’s useContext mostly.
this is open and up to you to implement, there is the reducer hook, which takes a similar approach
The issue I was finding was that the hooks are only valid to call within a component
Whereas in re-frame, I can just (rf/dispatch … ) anywhere
you can pass something to your root component
here is an example of a mini-reframe in Helix:
(defonce dispatcher* (atom nil))
(defonce app-state* (atom {::counter 0}))
(defmulti dispatcher (fn [action data state] action))
(defmethod dispatcher ::count-up [_ data state]
(update state ::counter #(inc (or % 0))))
(defn dispatch [state [action data :as foo]]
(reset! app-state* (dispatcher action data state)))
(defn repl-dispatch [cmd]
(@dispatcher* cmd))
(h/defnc MiniReframe []
(let [[state dispatch] (hooks/use-reducer dispatch @app-state*)]
(hooks/use-effect [dispatch] (reset! dispatcher* dispatch))
(dom/div
(dom/button {:on-click #(dispatch [::count-up])} (::counter state)))))
(comment
(repl-dispatch [::count-up]))
Very cool. Thanks!
one thing I've been doing some spending some hammock time on is a way to interact with React's low level stuff from a REPL
today I had an idea for a new state management system, something to combine hooks convenience and Fulcro robustness, going to try a POC on it later, this could address some of the issue of REPL interaction too
e.g. you can use the devtool hooks to get a reference to the currently rendered root fiber and traverse it to find components, inspect props and state, even get references to state setters & reducer dispatch fns which you can call to trigger renders
> even get references to state setters & reducer dispatch fns which you can call to trigger renders Oh this could be a really cool way to interact with an app. I’ve been getting around this by doing something similar to what @wilkerlucio shared above.
yeah the hooks are all there, the interface is what I'm still noodling on
sneak peak of my POC, showing a bit what user code may look like:
(h/defnc IKey [{:keys [attr]}]
(let [state (use-root-state app [attr] {})]
(dom/div "Render: " (pr-str (get state attr)))))
(h/defnc User [{:keys [user-id]}]
(let [{:user/keys [id name] :as props}
(use-entity-state app [:user/id user-id]
[:user/id :user/name]
{::load true})]
(dom/div
(dom/button {:on-click #(update-state props (fn [x] (assoc x :user/id 1 :user/name "bla")))} "Set data")
(dom/div "User")
(dom/div "ID: " id)
(dom/div "Name: " name))))
(h/defnc MyStateManager []
(dom/div
(h/$ IKey {:attr :foo})
(h/$ User {:user-id 123})
(h/$ User {:user-id 123})
(dom/button {:on-click #(update-state app (fn [x] (assoc x :foo "bar")))}
"Change text")))
the idea is to use hooks to plug some components in a "application" managed upstream (currently passing by hand, but it can go in a context to avoid repetition and make a tree use the same consistent app)
then you can hook on some root part, or in some entity (kind like Fulcro does)
the hook includes a query, and notifications are saved to fire refresh on things on state updates
what I like about it is that is veery opt-in, you can add this just for the parts of application that you want shared data
and can freely combine with other sorts of local state, like the state hook
options like ::load true
can make the component automatic trigger a remote load for that data, otherwise it just tries to denormalize it from the local db
I think there can be a lot of controls to decide how load should behave
looks really nice. this is the kind of use case that I built https://github.com/lilactown/autonormal for