使用回调和记忆

useCallback and memoization

记忆的回调函数是如何工作的?在一些文章中,我读到如果我们不使用 useCallback,就会重新创建该函数。但是,如果重新创建,它应该与以前的版本不同吗?在我的代码中,我没有注意到回调函数存在差异。 我的问题是:为什么在这两种情况下,我的设置大小都是 1?

来自 off doc useCallback

Returns a memoized callback.

Pass an inline callback and an array of dependencies. useCallback will return a memoized version of the callback that only changes if one of the dependencies has changed. This is useful when passing callbacks to optimized child components that rely on reference equality to prevent unnecessary renders (e.g. shouldComponentUpdate).

import { useCallback } from "react";

const dataSource = [
    {
        id: 1,
        model: "Honda",
        color: "red",
    },
    {
        id: 2,
        model: "Mazda",
        color: "yellow",
    },
    {
        id: 3,
        model: "Toyota",
        color: "green",
    },
];

const Car = ({ model, color, set, onCarClick }) => {
    const onClick = () => onCarClick(model, color);
    set.add(onCarClick);
    console.log(set.size);
    return (
        <div onClick={onClick}>
            Model: {model} Color: {color}
        </div>
    );
};

const CarsCallback = ({ cars, set }) => {
    const onCarClick = (model, color) => {
        console.log(model, color);
    };
    console.log("CarsCallback");
    return (
        <>
            {cars.map((car) => {
                return (
                    <Car
                        key={car.id}
                        set={set}
                        {...car}
                        onCarClick={onCarClick}
                    />
                );
            })}
        </>
    );
};

const CarsUseCallback = ({ cars, set }) => {
    const onCarClick = useCallback((model, color) => {
        console.log(model, color);
    }, []);
    console.log("CarsUseCallback");
    return (
        <>
            {cars.map((car) => {
                return (
                    <Car
                        key={car.id}
                        {...car}
                        set={set}
                        onCarClick={onCarClick}
                    />
                );
            })}
        </>
    );
};

export default function App() {
    return (
        <div className="App">
            <CarsCallback cars={dataSource} set={new Set()} />
            <CarsUseCallback cars={dataSource} set={new Set()} />
        </div>
    );
}

因为CarsUseCallbackCarsCallback触发了一次

我们可以看到CarsUseCallbackCarsCallback的唯一一条日志。

如果我们re-render CarsUseCallbackCarsCallback,我们可以看到大小是12

const CarsCallback = ({ cars, set }) => {
  const [count, setCount] = useState(1);
  console.log('CarsCallback');
  useEffect(() => {
    setCount(2);
  }, []);
  // ...

};

const CarsUseCallback = ({ cars, set }) => {
  const [count, setCount] = useState(1);
  console.log('CarsUseCallback');

  useEffect(() => {
    setCount(2);
  }, []);
  // ...

}