Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[EPIC] Move away from Reagent #18800

Open
1 of 4 tasks
flexsurfer opened this issue Feb 13, 2024 · 1 comment
Open
1 of 4 tasks

[EPIC] Move away from Reagent #18800

flexsurfer opened this issue Feb 13, 2024 · 1 comment
Assignees
Labels
feature feature requests mobile-core

Comments

@flexsurfer
Copy link
Member

flexsurfer commented Feb 13, 2024

Reagent compiles hiccup

Hiccup is a library that was created for Clojure which was mostly used on HTTP servers for generating HTML templates and it was very convenient for that. But do we need it in our RN application, do we use all its benefits, the answer is no. So basically we don’t need hiccup, and we could just use function calls like

(defn greeting [name] 
  (text (str "Hello " name " Welcome!")))

(defn app []
   (greeting "Taylor"))

currently, we just paying the computation price just because Reagent uses Hiccup

Reagent manages state with reactive atoms and forceUpdate React components

With the advent of React hooks for the state, this is no longer a killer feature, so it can be easily replaced by React hooks. But here there is more of a struggle between approaches, Clojure programmers will say that the use of atoms is more idiomatic, on the other hand, JS React developers and accordance with the React development standards

Reagent allows to pass props as arguments instead of one prop object how it’s in React

It’s a downside. It’s confusing, because React always passes props in the first argument as an object, and it might be confusing for devs when they work with Reagent. It might be restricted by guidelines, but it’s hard to follow

Reagent converts kebab to camel case and cljs to js objects

This is controversial, for some devs, it's more convenient, but for others not and it's better to use "native" js props in camelCase for them

Reagent uses deprecated classes instead of functional components

When Reagent was created, there were only class components, they were stateful and had different properties for the component lifecycle. Then later React replaced them by light functional stateless components and introduced hooks for them. Hooks can’t be used in class components, that’s why they can’t be used in Reagent functions.

An article with more technical detail can be found here Reagent under the hood

Also here the first successful experiment in UI development without Reagent. But there has been a lot of discussion and some disagreement, so we must develop a program of steps to phase out the Reagent gradually

First, we need to replace reactive atoms with react hooks for the state, but hooks can be used only in functional components.

so the steps will be as follows

(def functional-compiler (reagent.core/create-compiler {:function-components true}))

#18802

  • 2) replace reagent atoms with react hooks

this might take some time, because it cannot be automated, also at that time we should have an agreement in the team that reactive atoms are not used anymore in the new code

#18803

  • 3) change re-frame subscriptions to be used as react hooks (implemented here)

  • 4) replace reagent hiccup compiler with custom one (implemented here)

at this point reagent will be used only as reactive atom in re-frame subscriptions,

then later we could decide if we want go next and replace hiccup with functions calls, and replace cljs data for props with js data

@flexsurfer flexsurfer added the feature feature requests label Feb 13, 2024
@flexsurfer flexsurfer changed the title [EPIC] Moving away from Reagent [EPIC] Move away from Reagent Feb 13, 2024
@flexsurfer
Copy link
Member Author

flexsurfer commented Feb 13, 2024

Example of reagent atom replacement

before

(defn- view-internal
  [_]
  (let [pressed?     (reagent/atom false)
        on-press-in  #(reset! pressed? true)
        on-press-out #(reset! pressed? nil)]
    (fn
      [{:keys [on-press on-long-press disabled? theme container-style]}]
      [rn/pressable
       {:accessibility-label :log-out-button
        :on-press            on-press
        :on-press-in         on-press-in
        :on-press-out        on-press-out
        :on-long-press       on-long-press
        :disabled            disabled?
        :style               (merge (style/main {:pressed?  @pressed?
                                                 :theme     theme
                                                 :disabled? disabled?})
                                    container-style)}
       [icon/icon :i/log-out {:color (if pressed? colors/white-opa-40 colors/white-opa-70)}]
       [text/text {:weight :medium :size :paragraph-1}
        (i18n/label :t/logout)]])))

after

(defn- view-internal
  [{:keys [on-press on-long-press disabled? theme container-style]}]
  (let [[pressed? set-pressed] (use-state false)
        on-press-in  (use-callback #(set-pressed true))
        on-press-out (use-callback #(set-pressed nil))]
    [rn/pressable
       {:accessibility-label :log-out-button
        :on-press            on-press
        :on-press-in         on-press-in
        :on-press-out        on-press-out
        :on-long-press       on-long-press
        :disabled            disabled?
        :style               (merge (style/main {:pressed?  @pressed?
                                                 :theme     theme
                                                 :disabled? disabled?})
                                    container-style)}
       [icon/icon :i/log-out {:color (if pressed? colors/white-opa-40 colors/white-opa-70)}]
       [text/text {:weight :medium :size :paragraph-1}
        (i18n/label :t/logout)]])))

actually, this is a good example, because it has a mistake, (if pressed? colors/white-opa-40 colors/white-opa-70) here atom is used and not a value @pressed?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature feature requests mobile-core
Projects
Status: Backlog
Development

No branches or pull requests

2 participants