javascriptreactjsreact-hooks

Is it possible to share states between components using the useState() hook in React?


I was experimenting with the new Hook feature in React. Considering I have the following two components (using React Hooks) -

const HookComponent = () => {
  const [username, setUsername] = useState('Abrar');
  const [count, setState] = useState();
  const handleChange = (e) => {
    setUsername(e.target.value);
  }

  return (
    <div>
      <input name="userName" value={username} onChange={handleChange}/>
      <p>{username}</p>
      <p>From HookComponent: {count}</p>
    </div>
  )
}


const HookComponent2 = () => {
  const [count, setCount] = useState(999);
  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

Hooks claim to solve the problem of sharing stateful logic between components but I found that the states between HookComponent and HookComponent2 are not sharable. For example the change of count in HookComponent2 does not render a change in the HookComponent.

Is it possible to share states between components using the useState() hook?


Solution

  • If you are referring to component state, then hooks will not help you share it between components. Component state is local to the component. If your state lives in context, then useContext hook would be helpful.

    Fundamentally, I think you misunderstood the line "sharing stateful logic between components". Stateful logic is different from state. Stateful logic is stuff that you do that modifies state. For e.g., a component subscribing to a store in componentDidMount() and unsubscribing in componentWillUnmount(). This subscribing/unsubscribing behavior can be implemented in a hook and components which need this behavior can just use the hook.

    If you want to share state between components, there are various ways to do so, each with its own merits:

    1. Lift State Up

    Lift state up to a common ancestor component of the two components.

    function Ancestor() {
        const [count, setCount] = useState(999);
        return <>
          <DescendantA count={count} onCountChange={setCount} />
          <DescendantB count={count} onCountChange={setCount} />
        </>;
      }
    

    This state sharing approach is not fundamentally different from the traditional way of using state, hooks just give us a different way to declare component state.

    2. Context

    If the descendants are too deep down in the component hierarchy and you don't want to pass the state down too many layers, you could use the Context API.

    There's a useContext hook which you can leverage on within the child components.

    3. External State Management Solution

    State management libraries like Redux or Mobx or Zustand. Your state will then live in a store outside of React and components can connect/subscribe to the store to receive updates.