如何在不一直重新渲染的情况下为函数值创建 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 中的 useCallback
。 https://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 将旧值与新值进行比较时,它会检测到它们是相同的并保持不变。
我正在使用带钩子的 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 中的 useCallback
。 https://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 将旧值与新值进行比较时,它会检测到它们是相同的并保持不变。