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.

Answer from Yangshun Tay on Stack Overflow
🌐
GitHub
github.com › betula › use-between
GitHub - betula/use-between: Sharing state between React components
useBetween is a way to call any hook. But so that the state will not be stored in the React component. For the same hook, the result of the call will be the same. So we can call one hook in different components and work together on one state.
Starred by 291 users
Forked by 15 users
Languages   TypeScript 98.7% | JavaScript 1.3% | TypeScript 98.7% | JavaScript 1.3%
🌐
npm
npmjs.com › package › use-between
use-between - npm
December 26, 2022 - useBetween is a way to call any hook. But so that the state will not be stored in the React component. For the same hook, the result of the call will be the same. So we can call one hook in different components and work together on one state.
      » npm install use-between
    
Published   Nov 29, 2025
Version   1.4.0
Author   Slava Bereza
🌐
React
react.dev › reference › react › use
use – React
You are either calling use outside of a React Component or Hook function, or calling use in a try–catch block. If you are calling use inside a try–catch block, wrap your component in an Error Boundary, or call the Promise’s catch to catch the error and resolve the Promise with another value.
Top answer
1 of 10
164

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.

2 of 10
96

It is possible without any external state management library. Just use a simple observable implementation:

function makeObservable(target) {
  let listeners = []; // initial listeners can be passed an an argument aswell
  let value = target;

  function get() {
    return value;
  }

  function set(newValue) {
    if (value === newValue) return;
    value = newValue;
    listeners.forEach((l) => l(value));
  }

  function subscribe(listenerFunc) {
    listeners.push(listenerFunc);
    return () => unsubscribe(listenerFunc); // will be used inside React.useEffect
  }

  function unsubscribe(listenerFunc) {
    listeners = listeners.filter((l) => l !== listenerFunc);
  }

  return {
    get,
    set,
    subscribe,
  };
}

And then create a store and hook it to react by using subscribe in useEffect:

const userStore = makeObservable({ name: "user", count: 0 });

const useUser = () => {
  const [user, setUser] = React.useState(userStore.get());

  React.useEffect(() => {
    return userStore.subscribe(setUser);
  }, []);

  const actions = React.useMemo(() => {
    return {
      setName: (name) => userStore.set({ ...user, name }),
      incrementCount: () => userStore.set({ ...user, count: user.count + 1 }),
      decrementCount: () => userStore.set({ ...user, count: user.count - 1 }),
    }
  }, [user])

  return {
    state: user,
    actions
  }
}

And that should work. No need for React.Context or lifting state up

🌐
DEV Community
dev.to › betula › reuse-react-hooks-in-state-sharing-1ell
Reuse React hooks in state sharing - DEV Community
April 17, 2021 - We used the standard React hooks that are familiar and understandable to everyone to create a shared state between any components using just one external hook useBetween.
🌐
CodeSandbox
codesandbox.io › examples › package › use-between
use-between examples - CodeSandbox
reactReact example starter project · shared-states-and-props-between-components · george.gaurav · floral-wildflower-pp0bg · betula · Counter with useBetweenSharing React hooks stateful logic between components · betulaFind more examples or templates · AboutHow to share React hooks state between components9,614Weekly Downloads ·
🌐
React
react.dev › learn › sharing-state-between-components
Sharing State Between Components – React
This is known as lifting state up, and it’s one of the most common things you will do writing React code. How to share state between components by lifting it up ... Each Panel component has a boolean isActive state that determines whether its content is visible. ... import { useState } from 'react'; function Panel({ title, children }) { const [isActive, setIsActive] = useState(false); return ( <section className="panel"> <h3>{title}</h3> {isActive ?
🌐
LinkedIn
linkedin.com › pulse › how-share-react-hooks-between-components-slava-bereza
How to share React hooks state between components
November 6, 2020 - import React, { useState, useCallback } from 'react'; import { useBetween } from 'use-between'; const useCounter = () => { const [count, setCount] = useState(0); const inc = useCallback(() => setCount(c => c + 1), []); const dec = useCallback(() => setCount(c => c - 1), []); return { count, inc, dec }; }; const useSharedCounter = () => useBetween(useCounter); const Count = () => { const { count } = useSharedCounter(); return <p>{count}</p>; }; const Buttons = () => { const { inc, dec } = useSharedCounter(); return ( <> <button onClick ​={inc}>+</button> <button onClick ​={dec}>-</button> </> ); }; const App = () => ( <> <Count /> <Buttons /> <Count /> <Buttons /> </> ); export default App;
Find elsewhere
🌐
React
legacy.reactjs.org › docs › hooks-overview.html
Hooks at a Glance – React
React provides a few built-in Hooks like useState. You can also create your own Hooks to reuse stateful behavior between different components.
🌐
Open Collective
opencollective.com › use-between
use-between - Open Collective
June 7, 2022 - useBetween hook is the solution to your problem 😚 useBetween is a way to call any hook. But so that the state will not be stored in the React component. For the same hook, the result of the call will be the same.
🌐
React
legacy.reactjs.org › docs › hooks-rules.html
Rules of Hooks – React
Instead, always use Hooks at the top level of your React function, before any early returns. By following this rule, you ensure that Hooks are called in the same order each time a component renders. That’s what allows React to correctly preserve the state of Hooks between multiple useState ...
🌐
GitHub
github.com › streamich › react-use
GitHub - streamich/react-use: React Hooks — 👍
Collection of essential React Hooks. Port of libreact. Translations: 🇨🇳 汉语 ... createReducerContext and createStateContext — factory of hooks for a sharing state between components. useDefault — returns the default value when state is null or undefined.
Starred by 44K users
Forked by 3.3K users
Languages   TypeScript 99.5% | JavaScript 0.5%
Top answer
1 of 6
57

The dependency type between the components will define the best approach.

For instance, redux is a great option if you plan to have a central store. However other approaches are possible:

  • Parent to Child

    1. Props
    2. Instance Methods
  • Child to Parent

    1. Callback Functions
    2. Event Bubbling
  • Sibling to Sibling

    1. Parent Component
  • Any to Any

    1. Observer Pattern
    2. Global Variables
    3. Context

Please find more detailed information about each of the approaches here

2 of 6
31

What you want is to implement some object that stores your state, that can be modified using callback functions. You can then pass these functions to your React components.

For instance, you could create a store:

function Store(initialState = {}) {
  this.state = initialState;
}
Store.prototype.mergeState = function(partialState) {
  Object.assign(this.state, partialState);
};

var myStore = new Store();

ReactDOM.render(
  <FirstComponent mergeState={myStore.mergeState.bind(myStore)} />,
  firstElement
  );
ReactDOM.render(
  <SecondComponent mergeState={myStore.mergeState.bind(myStore)} />,
  secondElement
  );

Now, both the FirstComponent and SecondComponent instances can call this.props.mergeState({ . . .}) to assign state to the same store.

I leave Store.prototype.getState as an exercise for the reader.

Note that you can always pass the store (myStore) itself to the components; it just feels less react-y to do so.

Here is some more documentation that might be of interest:

React Docs: "Communicate Between Components"

For communication between two components that don't have a parent-child relationship, you can set up your own global event system. Subscribe to events in componentDidMount(), unsubscribe in componentWillUnmount(), and call setState() when you receive an event. Flux pattern is one of the possible ways to arrange this.

🌐
useHooks
usehooks.com
useHooks – The React Hooks Library
The all new interactive way to master modern React (for fun and profit). Manage complex state objects with useObjectState. Debug lifecycle events with useLogger. Dynamically update the title of a webpage with useDocumentTitle. Differentiate between the first and subsequent renders with useIsFirstRender.
🌐
ReactUse
reactuse.com
ReactUse - 110+ Essential React Hooks Library for TypeScript | ReactUse
ReactUse (@reactuses/core) is an open-source library of 110+ custom React Hooks for building production applications. It provides TypeScript-first, tree-shakable, and SSR-compatible hooks covering browser APIs, state management, DOM observation, ...
Author   childrentime
🌐
JavaScript in Plain English
javascript.plainenglish.io › i-tried-reacts-use-hook-in-my-project-here-s-what-blew-my-mind-a484bd1bc8e5
I Tried React’s use() Hook in My Project—Here’s What Blew My Mind | by Partha Roy | JavaScript in Plain English
July 15, 2025 - Also checkout: React Suspense and Lazy: Simplified Guide with Code Examples · I found use() very useful in scenarios where I needed data to be fetched before rendering the component. Instead of splitting logic between useEffect, states, and loading spinners, I could directly get the data with use(fetchSomething()).
🌐
React
react.dev › reference › react › useState
useState – React
It updates the screen after all the event handlers have run and have called their set functions. This prevents multiple re-renders during a single event. In the rare case that you need to force React to update the screen earlier, for example to access the DOM, you can use flushSync.
🌐
npm
npmjs.com › package › react-use
react-use - npm
Collection of React Hooks. Latest version: 17.6.0, last published: a year ago. Start using react-use in your project by running `npm i react-use`. There are 3424 other projects in the npm registry using react-use.
      » npm install react-use
    
Published   Dec 09, 2024
Version   17.6.0
Author   @streamich