helix

https://github.com/Lokeh/helix
wilkerlucio 2021-02-09T01:23:46.002800Z

is there a way to use componentDidCatch with Helix? (aka error boundaries: https://reactjs.org/docs/error-boundaries.html)

lilactown 2021-02-10T17:25:54.011900Z

there is, you can use defcomponent which defines a class component that you can implement componentDidCatch and other lifecycle methods

lilactown 2021-02-10T17:26:00.012100Z

it's very under-documented tho

Derek Passen 2021-02-09T16:38:18.004200Z

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.

wilkerlucio 2021-02-09T16:46:29.005100Z

this is open and up to you to implement, there is the reducer hook, which takes a similar approach

Derek Passen 2021-02-09T16:47:00.005300Z

The issue I was finding was that the hooks are only valid to call within a component

Derek Passen 2021-02-09T16:47:15.005500Z

Whereas in re-frame, I can just (rf/dispatch … ) anywhere

wilkerlucio 2021-02-09T17:11:42.005700Z

you can pass something to your root component

wilkerlucio 2021-02-09T17:30:14.005900Z

here is an example of a mini-reframe in Helix:

wilkerlucio 2021-02-09T17:30:16.006100Z

(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]))

Derek Passen 2021-02-09T17:30:42.006300Z

Very cool. Thanks!

lilactown 2021-02-09T21:44:47.006500Z

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

2👍
wilkerlucio 2021-02-09T21:45:52.006800Z

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

2👀
lilactown 2021-02-09T21:46:24.007Z

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

1👀
oconn 2021-02-09T21:51:13.007500Z

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

lilactown 2021-02-09T22:03:28.007800Z

yeah the hooks are all there, the interface is what I'm still noodling on

wilkerlucio 2021-02-09T22:56:20.008200Z

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")))

wilkerlucio 2021-02-09T22:57:11.008400Z

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)

wilkerlucio 2021-02-09T22:57:39.008600Z

then you can hook on some root part, or in some entity (kind like Fulcro does)

wilkerlucio 2021-02-09T22:57:58.008800Z

the hook includes a query, and notifications are saved to fire refresh on things on state updates

wilkerlucio 2021-02-09T22:58:18.009Z

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

wilkerlucio 2021-02-09T22:58:34.009200Z

and can freely combine with other sorts of local state, like the state hook

wilkerlucio 2021-02-09T23:00:04.009400Z

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

wilkerlucio 2021-02-09T23:00:14.009600Z

I think there can be a lot of controls to decide how load should behave

lilactown 2021-02-09T23:57:59.009800Z

looks really nice. this is the kind of use case that I built https://github.com/lilactown/autonormal for