2

I have a async function in a custom hook which should update the state but it doesn't

export const useXYZ = () => {
    const [XYZ, setXYZ] = useState([])
    const update = () => {
        BackendService.getAllXYZ().then(
            ({data}) => {
//------------>>> here I want to update, but if I use the hook it doesnt update if I call update()
                setXYZ(data)
            }
        ).catch((error)=>{
        })
    }
    return [XYZ, update]
}

1 Answer 1

1

Here is a minimal complete example of a custom hook with asynchronous state update and how it can be used in your component.

function App() {
  const [d1, roll1] = useDice(6)
  const [d2, roll2] = useDice(20)
  const [d3, roll3] = useDice(8)
  return <div>
    <button type="button" onClick={roll1} children={d1 || "roll"} />
    <button type="button" onClick={roll2} children={d2 || "roll"} />
    <button type="button" onClick={roll3} children={d3 || "roll"} />
    <pre>{JSON.stringify([d1, d2, d3], null, 2)}</pre>
  </div>
}

function useDice(sides = 6) {
  const [value, setValue] = React.useState(null)
  return [
    value,
    event => {
      setValue("...")
      setTimeout(_ => setValue(Math.floor(Math.random() * sides) + 1), 1000)
    }
  ]
}

ReactDOM.render(<App/>, document.querySelector("#app"))
button {
  width: 3rem;
  line-height: 3rem;
  margin: 0 0.5rem;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.14.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.14.0/umd/react-dom.production.min.js"></script>
<div id="app"></div>

Custom hooks can return any number of values of any type. Consider this alternative abstraction that returns a value and a component without the need to assign event handlers.

function App() {
  const [value1, d1] = useDice(6)
  const [value2, d2] = useDice(20)
  const [value3, d3] = useDice(8)
  return <div>
    {d1} {d2} {d3}
    <pre>{JSON.stringify([value1, value2, value3], null, 2)}</pre>
  </div>
}

function useDice(sides = 6) {
  const [value, setValue] = React.useState(null)
  function roll(event) {
    setValue("...")
    setTimeout(_ => setValue(Math.floor(Math.random() * sides) + 1), 1000)
  }
  return [
    value,
    <button type="button" onClick={roll} children={value || "roll"} />    
  ]
}

ReactDOM.render(<App/>, document.querySelector("#app"))
button {
  width: 3rem;
  line-height: 3rem;
  margin: 0 0.5rem;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.14.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.14.0/umd/react-dom.production.min.js"></script>
<div id="app"></div>

Sign up to request clarification or add additional context in comments.

4 Comments

sorry does not work
The codes on this page are executable and work. Have you tried them? "Sorry does not work" is not able to debug.
yes sorry. I meant for my use case. If put the function into the return it does not work
The example snippet works. In a similar use case I had to resort to useContext to make the hook work in child components.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.