【问题标题】:How does react keep variables value in useCallback?react如何在useCallback中保持变量值?
【发布时间】:2020-06-02 00:49:33
【问题描述】:
const { useState, useCallback } = React;
let globalValue = 0;
const ComponentA = ({ propValue }) => {
    const [sum, setSum] = useState(propValue);
    const [stateValue, setStateValue] = useState(0);
    const onClick = useCallback(() => {
        console.log(propValue, stateValue, globalValue);
        setSum(propValue + stateValue + globalValue);
    }, []);
    return (
        <div>
            <p>State value is {stateValue}</p>
            <p>Sum is {sum}</p>
            <button onClick={() => setStateValue(stateValue + 1)}>
                Set stateValue
              </button>
            <button onClick={() => globalValue += 1}>
                Set globalValue
            </button>
            <button onClick={onClick}>
                Get Sum
            </button>
        </div>
    );
};
const Parent = () => {
    const [propValue, setPropValue] = useState(0);

    return (
        <div>
            <p>Prop value is {propValue}</p>
            <button onClick={() => setPropValue(propValue + 1)}>
                Set PropValue
            </button>
            <ComponentA propValue={propValue} />
        </div>
    );
};

如果ComponentA中的useCallback的依赖列表设置为[],则在执行console.log时,无论当前的propValuestateValue是什么,它们都将永远是@987654328 @。但是globalValue 将始终使用最新的。当我检查propValuestateValue__proto__时,它们都只是原始类型。

useCallback 钩子如何保持变量的原始值?难道它不应该遵守这样的规则,即如果一个变量没有在当前范围内定义,它将查找其父级并使用那里的值(如globalValue)?

我知道这就是useCallback/useMemo 的重点,但这是如何实现的?

【问题讨论】:

  • 这是一个闭包。

标签: javascript reactjs scope react-hooks


【解决方案1】:

我从这个博客https://dmitripavlutin.com/react-hooks-stale-closures/找到了答案

这里是useCallback的模拟代码。

(function () {
    const ReactDomTree = {};
    const memo = {};
    const getButtonElement = () => { return ReactDomTree.buttonA };
    function useMemo(create) {
        if (!memo.result) {
            memo.result = create();
        }

        return memo.result;
    };

    const useCallback = function (callback) {
        return useMemo(() => callback);
    }


    function component() {
        let propValue = Math.floor(Math.random() * 100); // mimic prop update
        let stateValue = Math.floor(Math.random() * 100); // mimic state update
        console.log('component render', propValue, stateValue);

        const onClick = useCallback(() => {
            console.log('onclick', propValue, stateValue);
        });

        if (!ReactDomTree.buttonA) {
            ReactDomTree.buttonA = {};
            ReactDomTree.buttonA.onClick = onClick;
        }
    }

    component(); // component render
    let button = getButtonElement()
    button.onClick();
    component(); // component render
    button = getButtonElement()
    button.onClick() // This log result is same as the previous one

})();

【讨论】:

    猜你喜欢
    • 2011-09-20
    • 2022-11-02
    • 2020-09-16
    • 2023-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-02
    相关资源
    最近更新 更多