0

I have created a custom hook to toggle between items from an array. This is the custom hook and how we use it in a component.

const { useState } = React;

function useToggleItems (arr){
    const [count,setCount] = useState(0);
    const [item , setItem] = useState(arr[count]);


    function toggle(){
        if(count<arr.length-1)
        {
          setCount(prev=>prev+1);
        }
        else
        {
          setCount(0);
        }
        setItem(arr[count]);
    }

    console.log(count);
    return [item, toggle];
}


function App() {

  const [item , toggle] = useToggleItems([1,2]);

  return (
    <div className="App">
      <h1>{item}</h1>
      <button onClick={toggle}>Button</button>
    </div>
  );
}

ReactDOM.createRoot(document.querySelector("#root")).render(<App />);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js"></script>

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

I have tried to make this work but i don't know why it is forming a stale closure on first click and DOM is not getting updated with current value of count from useState. But after the first click it starts to work fine. Can some one help me fix this stale closure issue.

const [item,toggle] = useToggleItems(['a','b','c']);
skyboyer
  • 22,209
  • 7
  • 57
  • 64
Snehil Agrahari
  • 307
  • 1
  • 15
  • 2
    Can you please add your code as text (not as an image [Why should I not upload images of code/data/errors?](https://meta.stackoverflow.com/q/285551))? Are you also able to share where you're calling `toggle()` – Nick Parsons Dec 26 '22 at 12:37
  • 1
    Ok. just give me a minute – Snehil Agrahari Dec 26 '22 at 12:37
  • Thanks for letting me know I can do things like this. @NickParsons – Snehil Agrahari Dec 26 '22 at 12:45
  • 1
    No worries, thanks for updating your code. Your issue is with `toggle()`. You're assuming that calling `setCount()` will change the value of `count` immediately, but this is not the case. It is only once React rerenders your component is the new value of `count` is available. See [this answer](https://stackoverflow.com/a/58877875/5648954) and the heading **"use a temporary variable"** to see how you can create a temporary variable (eg: `newCount`) within your `toggle` function, and then use that when setting your `item` state: `setItem(arr[newCount]);` – Nick Parsons Dec 26 '22 at 12:49
  • 2
    Yea got it .. I removed the setitem from function to useEffect and added count as dependency. This has actually fixed the issue and I understood what the problem actually was. – Snehil Agrahari Dec 26 '22 at 12:51

0 Answers0