3 ms·
Looks like the default way of writing react components in ClojureScript (with Reagent [1]). Compare: CLJS, Reagent: (def click-count (r/atom 0)) (defn
by emmanueloga_ 8y ago
Looks like the default way of writing react components in ClojureScript (with Reagent [1]). Compare:
CLJS, Reagent:
(def click-count (r/atom 0))
(defn counting-component []
[:div
"The atom " [:code "click-count"] " has value: "
@click-count ". "
[:input {:type "button" :value "Click me!"
:on-click #(swap! click-count inc)}]])
JS, React + Hooks:
function Example() {
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>);}
Not sure about the name "hooks". Trying to figure out why they name them like that.
1: https://reagent-project.github.io/ https://reagent-project.github.io/
- lilactown 8y agoYep. It looks like React is eating Reagent's lunch and I'm super excited about it!
- bschwindHN 8y agoThis is a bizarre comment to me. React is already used _way_ more than Reagent. Even Reagent itself uses React internally. What "lunch" is there to eat? People who enjoy ClojureScript will still use Reagent/Re-Frame because it's not JavaScript.
- fnordsensei 8y agoI think it refers to adopting a pattern from Reagent. Throughout its lifetime, React does seem to have had a mutually beneficial relationship with the ClojureScript ecosystem, with select ideas from Reagent, Om and others being adopted in core React, or as JS libraries around it.
- lilactown 8y agoIn the small world of the CLJS ecosystem, we use some very elaborate wrappers around React (for good and bad reasons). I'm excited to have many of the features we have had to implement and maintain in user land be moved into React proper, so that we can remove swathes of code that were filling in gaps in the React framework. In general, I am much more confident in the React team supporting these concerns - simply because there's WAYYY more time, money and mindshare involved - than the CLJS ecosystem shouldering the burden.
- rpeden 8y agoI don't think it's quite the same, is it? In the Reagent example, you declare the atom outside of the component function, and that atom would end up shared if there were multiple instances of the counting component. In the react example, each instance of the component would have its own separate state. Reagent will let you put the atom inside the component, too, so you can do something very similar to the React example. Just wanted to point out that the two examples you've got now do different things.
- emmanueloga_ 8y agohmmm yeah here's a better example: (defn timer-component [] (let [seconds-elapsed (r/atom 0)] (fn [] (js/setTimeout #(swap! seconds-elapsed inc) 1000) [:div "Seconds Elapsed: " @seconds-elapsed]))) Now the atom is defined inside the component function, and is captured by lexical scope in the returned function. Any timer-components on page will have their own `seconds-elapsed` state.
- wildermuthn 8y agoThis was such a common pattern that reagent created a macro for it. But I like the macro-less code, in that it becomes very clear what is happening. A good macro reduces complexity by making code concisely simple. A bad macro hides complexity by making code easy to write. Frameworks like React succeed when they are built like a good macro. In this case, React is both hiding complexity (component lifecycles) while adding unnecessary complexity (a lInter that will inevitably fail). It’s odd to see React make this move, but not surprising considering that it now has a larger use-base then ever before.
- emmanueloga_ 8y agoAre you maybe talking about with-let? I'm fairly new to reagent and not really familiar with any of its macros As it turns, there are only 5 macros, and only a some of those seem to be part of the public API, which is how I found about `with-let` :-) https://github.com/reagent-project/reagent/search?q=defmacro&unscoped_q=defmacro https://github.com/reagent-project/reagent/search?q=defmacro...