Comments (16)
I really value the approach in this project of providing a minimal wrapper, and respecting the semantics of React. The atom interface did look like a nice idea at first, but I think you're correct in identifying that there's a mismatch. On balance, I think I'd personally prefer the clarity of using the [state setState]
tuple as proposed in your merge request. Thanks for all the think-effort on this :)
from hx.
As far as I can tell, they’ve punted on trying to align Redux with Concurrent React’s scheduler. They’re essentially moving back to a similar architecture as v5, where they keep a synchronous store that dispatches renders to each component that subscribes to it.
AFAICT this is due to the fact that previous versions of Redux gave the guarantee that dispatch
is synchronous, so that you can do something like:
dispatch(FOO_EVENT);
store.getState();
This is exactly the same expectation that is broken by representing React useState as a Clojure atom.
If we do not carry forward this expectation, I think we might be able to align ourselves with React’s scheduler and leverage its benefits when it finally lands in stable.
from hx.
Yeah. The global state management problem is one of the most interesting at the moment w.r.t. Concurrent React, which is probably one of the reasons they aren’t willing to do a stable release with it yet 😄 .
FWIW I have the very strange (in CLJS) opinion that maintaining state outside of the render tree is an anti pattern, but even trying to maintain “global” state inside the render tree is waiting on improvements to context.
I have one approach that I want to test before I call it completely infeasible to do without the React team improving context. It involves maintaining global state inside of a top-level useRef
kept in context, and maintaining subscriptions inside of the components using local state. It could specifically take advantage of ClojureScript’s immutable data to be much more memory and CPU efficient.
I’ll see if I can come up with a POC in the next week or two - got to make sure I don’t spend too much of my limited brain power on this 😂
from hx.
Some discussions on the react-redux repo making for good reading:
from hx.
Something that becomes really obvious the moment you start storing state in React -- hot reloading becomes a little bit more annoying, as React will re-run all your hooks and re-fetch all data from the backend.
So the defonce trick for state that survives hot reloads doesn't really work.
My hacky workaround is to have a top-level defonce and then use that until the fresh data comes back from the backend, so at least then I don't "loading state" flashes when I work on presentational stuff.
from hx.
cc @orestis @mhuebert @roman01la
Also I have created some devcards of the above examples in the master
branch of this repo.
from hx.
Relevant article written by Andrew Clark: https://github.com/acdlite/rfcs/blob/context-write/text/0000-context-write.md#concurrent-invalidation
In it he talks about how maintaining state in a synchronous external store with concurrent renders can cause inconsistencies.
from hx.
Thanks for layout the issues so clearly. I would conclude the same thing as you, don't try to do non React thing, just embrace it.
But this raises a question for us Clojure(Script) developers: what could be the equivalent of global store in Clojure(Script) then? Should we just have a top level atom and add a watcher that re-render the top level component with the content of the atom passed as props (or React context) ? Use the useReducer hook and pass the dispatch function as props (or again pass it through context)? Just abandon Atoms and lose the observability they provide (this hurts somehow but may be ok)?
I'd love your thoughts on these questions, I don't have an answer.
from hx.
I've just read the proposal you linked from Andrew Clarke. Maybe we need to wait for a solution like this to allow using atoms and React together. What I mean is that we could reset!
the atom in the contextDidUpdate callback, so that the UI and the state stay consistent. But not sure if it's doable or a good idea, would need to see what to come up with.
In the meantime, given React don't have stable APIs for scheduling state transitions... I don't know 😅
from hx.
I'm interested to see what you come up with. I also had the idea that keeping the global state inside the top-level component could be a solution. Looking forward to seeing it!
from hx.
I've created a PR that removes the Atom-like wrapper around useState
, as well as optimizes certain cases where the state update fn might return a structurally equivalent but referentially different collection.
This aligns us with the semantics of React and users can expect similar/API behavior as the React docs say.
Looking for feedback!
from hx.
React-redux seems to have found a solution, since they've released a beta of version 7, which uses hooks and seems to just store the "global" content inside the UI tree itself, to let React handle it. Admittedly I've glanced quickly only, so you may want to read it carefully https://www.reddit.com/r/reactjs/comments/b40y7u/reactredux_v700beta0_faster_performance_and_built/
from hx.
from hx.
I don't use hx yet (I'm using Rum right now), but I'm keeping my eye on it because of the new stuff coming down the React pipeline (hooks, concurrent, etc), but I think this would be a good change to make it more consistent with React.
Are there synchronization issues with the component's state and an atom when using the <-deref
hook? I'm trying to wrap my head around how I would do state management with hooks in hx. Right now each line of my form subscribes to updates on the global atom when that line changes. This is for performance reasons so I'm not creating a react virtual Dom tree for my whole app on every keystroke.
from hx.
Yes, <-deref
is a foot-gun in concurrent React. Either you skip out on using scheduling with React, or you risk getting out or sync with your state.
from hx.
This is a very interesting discussion, thank you all for sharing it here. Shame I only become aware of it today!
I've been tinkering a lot about using something like citrus
together with the React hooks. I like the colocation of state and side effect and the ability of supplying different effect handlers for e.g. testing that citrus
gives you.
This is my best shot at recreating reducers with side effects in pure React, no extra atoms and observers.
https://gist.github.com/frankiesardo/d135c73d74695d83277c4294a987006f
I would love to hear the thoughts of people in this conversation since you've analysed the problem quite deeply
from hx.
Related Issues (20)
- Destructuring defnc :keys [class] has weird behaviour HOT 1
- Improved react dev-tools support for hooks HOT 3
- CLJS data structures are compared by ref in <-effect deps HOT 11
- class & className issue when wrapping defnc component with pure react component HOT 3
- Make it fast
- Experience Report HOT 7
- Reducers dont support Multimethods HOT 4
- Document hiccup parser API
- hx/f exceptions handlint HOT 4
- any HOT 1
- Export hooks under Clojure-style names HOT 2
- `defcomponent` API is very confusing HOT 1
- How-to contains misleading memo use HOT 7
- Push missing tags + maybe a 0.5.4 release HOT 2
- Docstring support for defnc (and defcomponent) HOT 1
- track dependencies to selectively rerender with useMemo HOT 3
- Passing down original js props in render props does not work with js->clj
- hx.hooks/useMemo deps as CLJS collection? HOT 1
- Typo in package 0.5.3 (maybe broken) HOT 3
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from hx.