How to wait for state to update without useEffect?

Basically I have custom hook that looks like this:
const [data, setData] = useState<ResponseType | null>(null)
const [isLoading, setLoading] = useState(false)
const [isRunning, setRunning] = useState(false)
const [err, setErr] = useState<Error | null>(null)

const execute = useMemo(
    () => async (input: z.infer<InputType>) => {
      setRunning(true)
      try {
        const result = await actionRef.current(input)
        setData(result)
        setRunning(false)
      } catch (e) {
        console.log(e)
        setErr(e as Error)
        setRunning(false)
      }
    },
    [],
  )
return {execute, data, isLoading, isRunning, err}

Then I call it like this:
const {execute, data} = useFoo()
async function doAction() {
    await execute({
      id: id,
    })
    console.log(data) // doesn't work, return stale data instead of waiting for execute to finish updating state
  }

Of course I can use useEffect but I prefer not to.
Was this page helpful?