skip to Main Content
const useCustomState = () => [value, setValue];
const [data, setData] = useCustomState(initValue);
useEffect(() => {
   const fn = async() => {
       await setData(1);
       console.log(data); // ouput 1
   };
   fn();
}, [])

How to implement this custom hooks function can get the latest value of data immediately after setting data in async syntax. I know it should be done by useEffect(() => console.log(data), [data]). But the useEffect all over the floor looks very inelegant

2

Answers


  1. We can create a custom useState hook as you desired.

    import { useEffect, useState, useCallback, useRef } from 'react';
    
    const useCustomState = (initValue) => {
      const [state, setState] = useState(initValue);
      const cbRef = useRef();
    
      const SetState = useCallback((newState, cb) => {
        cbRef.current = cb
        setState(newState);
      }, []);
    
      useEffect(() => {
        if (cbRef.current) {
          cbRef.current(state);
          cbRef.current = null;
        }
      }, [state]);
    
      return [state, SetState];
    }
    

    You can use this in your component like this as you wished:

    const [data, setData] = useCustomState(initValue);
    
    useEffect(() => {
      const fn = async() => {
        await setData(1, newData => {
          console.log(newData); // output 1
        });
      };
      fn();
    }, []);
    

    Plese read more about how to create custom hooks here and legacy features here

    You should remember that using a custom hook would still not eliminate the execution of useEffect since the components are asynchronous and depends on re-render cycle.

    Another option to get the result without creating a custom hook is by calling another useEffect in the same component which would fire upon any changes to the targeted state or prop.

    const [data, setData] = useState(initValue);
    
    useEffect(() => {
       const fn = async() => {
           await setData(1);
       };
       fn();
    }, []);
    
    useEffect(() => { //<---- Call another useEffect
       console.log(data); //<--- Here, it would show the result
    }, [data]); //<---- Listen to data changes
    
    Login or Signup to reply.
  2. If I understand you right you can make it without useEffect again you can see this video it explains how to do this and you can learn how to make dynamic Hook to able to use it many times

    https://www.youtube.com/watch?v=Jl4q2cccwf0&list=PL4cUxeGkcC9gZD-Tvwfod2gaISzfRiP9d&index=20

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search