search

Home  >  Q&A  >  body text

How to prevent state reset when calling state setter in 3rd party library

I'm trying to convert a React class component into a React function component.

There is a onChange function that can be called inside and outside the component. The useState hook gets the initial value when the function component function is called. When I use the old class component way everything works fine. Why does this happen and how to solve it?

const MyInput = (props) => {
  const { someLib, ...otherProps } = props;
  const [test, setTest] = useState(1); // console show 1,2,3, etc
            
  useEffect(() => {
    someLib && someLib.addCallback(onChange);
  }, []);

  const onChange = (event) => { 
    setTest(test + 1) // this function can called inside MyInput, and from someLib, 
                      // when it called from someLib, 'test' is reset, but in class component everything good 
  }
}

P粉835428659P粉835428659504 days ago664

reply all(1)I'll reply

  • P粉514001887

    P粉5140018872023-09-11 22:01:16

    The problem is that onChange is an obsolete closure. What you need to do is make onChange look like this:

    const onChange = (event) => {
        setTest(oldTest => oldTest +1)
    }
    

    Alternatively, you can add test to the dependencies array in useEffect, but make sure to clean it up. (You should do this anyway, but it’s more important now)

    useEffect(() => {
        someLib && someLib.addCallback(onChange);
    
        return () => {
            someLib.removeCallback(onChange);
        }
    }, [someLib, test]);
    

    Technically, if you are doing the latter approach, you need to useCallback

    const onChange = useCallback((event) => {
        setTest(test + 1);
    }, [test]);
    
    useEffect(() => {
        someLib && someLib.addCallback(onChange);
    
        return () => {
            someLib.removeCallback(onChange);
        }
    }, [someLib, onChange]);
    

    The advantage of this is that you don't have to track onChange's dependencies in different places. The dependency list for onChange is now closed.

    reply
    0
  • Cancelreply