Edit React state with Hooks

1.3k views Asked by At

I would like to have a global variable that I can edit anywhere using hooks.

In the example I have 2 components both using the same hook. It seems to me that the External toggle is editing its own scoped count and Internal Toggle is changing its own scope also.

Is it possible have both toggles edit the same data?

Code example: https://codesandbox.io/s/520zvyjwlp

index.js

function ChangeCount() {
  const { count, increment } = useCounter();
  return <button onClick={() => increment(!count)}>External Toggle</button>;
}

function App() {
  const { count, increment } = useCounter();
  return (
    <div>
      {`${count}`}
      <br />
      <ChangeCount />
      <br />
      <button onClick={() => increment(!count)}>Internal Toggle</button>
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement); 

useCount.js

import { useState } from "react";
export default function useCounter() {
  const [count, setCount] = useState(false);
  const increment = (changeCount) => setCount(changeCount);
  return { count, increment };
}
2

There are 2 answers

0
Jose Munoz On

To complete this task, you should share your state via the context API,

consider the following:

const CounterContext = React.createContext({
  count: 0,
  increment: () => null,
});

const changeCount = () => {
  const counter = useContext(CounterContext);

  return <button onClick={() => counter.increment(!counter.count)}>External Toggle</button>;
}

const App = () => {
  const { count, increment } = useCounter();
  return (
    <CounterContext.Provider value={{ count, increment }}>
      {`${count}`}
      <br />
      <ChangeCount />
      <br />
      <button onClick={() => increment(!count)}>Internal Toggle</button>
    </CounterContext.Provider>
  );
}

for more information please visit: https://reactjs.org/docs/context.html

5
Tholle On

As you've noticed custom hooks is for sharing stateful logic, not actual state.

If you want to share a piece of state you can use the context feature and pass the count variable and the increment function in an object to the value prop of the Provider and consume it further down the tree with useContext.

Example

const { createContext, useContext, useState } = React;
const CounterContext = createContext();

function ChangeCount() {
  const { increment } = useContext(CounterContext);
  return <button onClick={increment}>External increment</button>;
}

function App() {
  const [count, setCount] = useState(0);
  function increment() {
    setCount(count + 1);
  }

  return (
    <CounterContext.Provider value={{ count, increment }}>
      <div>{count}</div>
      <ChangeCount />
      <button onClick={increment}>Internal increment</button>
    </CounterContext.Provider>
  );
}

ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

<div id="root"></div>