Я использую React.Context для передачи некоторой функции моим вложенным дочерним компонентам.Чтобы сделать это, я передаю объект, который содержит все мои функции, в контекст следующим образом:
const MyComponents = props = {
const func1 = () => {
props.doSomething(props.value);
}
const func2 = () => {
props.doSomething2(props.value);
}
return (
<ProjectContext.Provider value={{func1, func2}}>
<NestedChildComponents />
</ProjectContext.Provider>
)
}
Проблема, с которой я сталкиваюсь, заключается в том, что при повторном рендеринге MyComponent
создается новый объект контекста.func1
и func2
имеют новые ссылки, и из-за этого все дочерние компоненты, которые используют ComponentContext
, также будут перерисованы.
Одним из решений, о котором я подумал, было обернуть мои функции в useCallback
, чтобы они не создавали ненужных новых ссылок, и обернуть значение контекста в useMemo
, чтобы контекст также не был воссозданесли не нужноЭто будет выглядеть примерно так:
const MyComponents = ({value1, value2, doSomething, doSomething2}) = {
const incrementCount = useCallback(() => {
doSomething(value1);
}, [value1, doSomething])
const func2 = useCallback(() => {
doSomething2(value2);
}, [value2, doSomething2])
const contextValue = useMemo(() => {
return {func1, func2};
}, [func1, func2])
return (
<ComponentContext.Provider value={contextValue}>
<NestedChildComponents />
</ComponentContext.Provider>
)
}
Это гарантирует, что не будет воссоздавать contextValue, если не нужно, так что это немного лучше.Тем не менее, у меня все еще есть проблема с этим решением, потому что, когда изменяется только func1
, весь мой объект контекста будет воссоздан и получит новую ссылку, что означает, что все дочерние компоненты будут перерисованы.
Можно ли повторно визуализировать дочерний компонент, только когда фактическая функция из контекста изменилась?Например, ChildComponent
использует ComponentContext.func1
, он не должен повторно отображаться при изменении ComponentContext.func2
.Я читал, что это можно сделать с помощью this.setState
, но я предпочитаю не использовать компонент Class, поэтому мне было интересно, есть ли другое решение.