P粉1704382852023-08-16 09:43:21
Yes, the purpose of useCallback
is to allow a function to keep its reference between renders unless the dependencies you specify have changed.
For example, if you have a function f(x,y)=>x y
, you can use an empty dependency array useCallback((x,y)=>x y,[ ])
, this function will never change. It always produces consistent behavior because it only uses its arguments to parse the output. However, it may change if you have another function h
and another external value z
, and h
is defined as h(x ,y)=>x y z
, then you need to include z
in the dependencies so that if z
changes, the value returned from useCallback
The function will have a new reference.
So the purpose of useCallback
is typically when you pass a function so it doesn't trigger a child component to re-render, or when you use a function as a function in a child component's useEffect
declaration dependencies. If the operations inside the function are expensive, then useCallback
is less useful and you should memorize the results separately.
Regarding the ref
thing, I think including ref
in the dependency doesn't do anything, it's like the array is empty. Maybe if ref
was stored in the state it might be useful, but I'm not really sure.
Here is a link https://stackblitz.com/edit/stackblitz-starters-wwyw9f?file=src/App.tsx, which has some examples, which may be useful.
If it might be deleted, I can also paste it over.
import * as React from 'react'; import './style.css'; export default function App() { //x and y to be used as function arguments const [x, setX] = React.useState(0); const [y, setY] = React.useState(0); //z is variable also used in function calculation but not as an argument const [z, setZ] = React.useState(0); const ref = React.useRef<number>(0); //counter to see how many times function updates //will start at 2 cause strict mode but that's no issue really const [i, setI] = React.useState(0); //function to add x and y from args and add z from state const fn = React.useCallback( (x: number, y: number) => { // console.log(`${x}+${y}`); return x + y + z; }, [z] // if you remove z and update it get wrong result ); //update fn count on fn change React.useEffect(() => { setI((i) => i + 1); }, [fn]); React.useEffect(() => { console.log('nice'); return () => console.log('ref cleanup'); }, [ref]); return ( <div> <pre>{JSON.stringify({ x, y, z })}</pre> <button onClick={() => setX((x) => x + 1)}> x ++</button> <button onClick={() => setY((y) => y + 1)}> y ++</button> <button onClick={() => setZ((z) => z + 1)}> z ++</button> <pre>x+y+z={fn(x, y)}</pre> <pre>fnCount:{i}</pre> <button onClick={() => { ref.current = ref.current++; }} > ref++ </button> </div> ); }
hope it is of help to you