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

[Hooks] An official global state-management solution (a la redux) #90

Closed
derrickbeining opened this issue Nov 20, 2018 · 4 comments
Closed

Comments

@derrickbeining
Copy link

derrickbeining commented Nov 20, 2018

Related to #68
I'm unsure if this is the appropriate place for this. If not, feel free to close.

The useState hook feels very similar to the way atoms work in reagent.cljs, except for one important part: in reagent, multiple components can share one atom so that all of them re-render when it changes, whereas useState only creates state local to the component that called it and only that component (and its children) re-render when that state changes. To say it another way, React hooks offer little to no affordance for doing scalable global state management in the fashion of redux or mobx, whereas reagent atoms do. However, I think it would be relatively simple to implement atoms for React with a light abstraction on top of useState and useMutationEffect.

I've already implemented a minimal version of Atom for react, and so far I really like the result. I'm curious to know what others think.

I'm just calling it react-atom for now and have published it (with TypeScript typings) to npm. Here are the docs. And here is a JS CodeSandbox and TS CodeSandbox to try it out live. If you're wondering, the API for it is mostly just plagiarized from clojure/script atoms.

I think there would be a lot of benefit to react.js providing something like this as an official way for doing global state management. Doing so would really help unify the community and library ecosystem, and it would allow some performance optimizations to be managed internally by react. It could be made more plug-able too, so as to enable the various niceties made possible by redux middleware.

The new Hooks proposal seems like the perfect opportunity to introduce something like this. What do you think?

@derrickbeining
Copy link
Author

derrickbeining commented Nov 20, 2018

Here is a basic example of what using an Atom looks like:

import React from 'react';
import ReactDOM from 'react-dom';
import {Atom, useAtom, swap} from '@dbeining/react-atom';
 
const stateAtom = Atom.of({
  text: '',
  data: {
    // ...just imagine
  },
});
 
const updateText = (evt) =>
  swap(stateAtom, (state) => ({...state, text: evt.target.value}));
 
const loadSomething = () =>
  fetch('https://jsonplaceholder.typicode.com/todos/1')
    .then((res) => res.json())
    .then((data) => swap(stateAtom, (state) => ({...state, data})))
    .catch(console.error);
 

const SomeComponent = () => {
  const {count, data, text} = useAtom(stateAtom);
 
  return (
    <div>
      <p>Text: {text}</p> 

      <button onClick={loadSomething}>
        Load Data
      </button>

      <input 
        type="text" 
        onChange={updateText} 
        value={text} />
 
      <p>{JSON.stringify(data, null, '  ')}</p>
    </div>
  );
};

const App = () => (
  <div>
    <SomeComponent /> // these components are kept in sync by useAtom
    <SomeComponent /> // these components are kept in sync by useAtom
  </div>
)
 
ReactDOM.render(<App />, document.getElementById('root'));

@mfrachet
Copy link

Doesn't this proposal provide a solution? #89

@derrickbeining
Copy link
Author

derrickbeining commented Nov 24, 2018

@mfrachet , yeah that's what @gaearon pointed out to me. #89 wasn't posted until the day after I finished prototyping react-atom so I missed it when I posted here. Context.write does seem to be getting at a similar problem, but I'm curious what differences there are in the implications for each approach.

react-atom simply uses useState hooks internally, so it works with concurrent rendering and Suspense to the same degree that useState does, and as far as I can tell,react-atom has no problem sharing/syncing state across multiple React roots -however, I probably don't understand well enough the issues @acdlite described about concurrent rendering, Suspense, and dealing with multiple roots.

@acdlite , if you happen to see this, I'd be super grateful to know what you think about react-atom and its viability as an alternative to enhancing the Context API.

@gaearon
Copy link
Member

gaearon commented Aug 24, 2021

Hi, thanks for your suggestion. RFCs should be submitted as pull requests, not issues. I will close this issue but feel free to resubmit in the PR format.

@gaearon gaearon closed this as completed Aug 24, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants