如何在不一直重新渲染的情况下为函数值创建 React Context

how to create React Context for a function value without re-rendering all the time

我正在使用带钩子的 React(没有 class 个组件)。

我目前有这样的代码:

function useTimerange()
{
    const [tr, setTr] = useState(defaultRange);

    function setCustomRange(range)
    {
        setTr(range);
    }

    return {tr, setCustomRange};
}

const ContextSetCustomTimerange = React.createContext(undefined);

function MyComponent(props)
{
    const {tr, setCustomRange} = useTimerange();

    return (
        <>
            <TimeRangePicker selectedRange={tr}/>
            <ContextSetCustomTimerange.Provider value={setCustomRange}>
              <MyChildComponent/>
            </ContextSetCustomTimerange.Provider>
        </>
    );
}

问题出在这一行:

<ContextSetCustomTimerange.Provider value={setCustomRange}>

由于传递的值是一个在每次 MyComponent 渲染时重新创建的函数,它会导致 Context 提供者每次都重新渲染它的所有消费者。

防止这种情况的最佳方法是什么?

您可以使用 React Hooks 中的 useCallbackhttps://reactjs.org/docs/hooks-reference.html#usecallback

import { useCallback } from 'react'

function useTimerange()
{
    const [tr, setTr] = useState(defaultRange);
    const setCustomRange = useCallback((range) => {
      setTr(range);
    }, [])

    return {tr, setCustomRange};
}

或者可能只是 return 直接 setTr

return {tr, setCustomRange: setTr};

这里的性能问题是,如果 setCustomRange 更改它的引用,它将触发为您的上下文呈现所有消费者,因为 React 正在比较引用。

我认为 useCallback 和 [] 一样,就像 Giang 提到的那样,这似乎是最好的主意。

你也可以传递一个state给provider值,然后把函数放在state上;由于保留了状态引用,并且当 React 将旧值与新值进行比较时,它会检测到它们是相同的并保持不变。