问题来自于useContext
。每当上下文中的任何值发生变化时,无论您使用的值是否发生变化,组件都会重新渲染。
解决方案是创建一个 HOC(即withMyContext()
)像这样;
// MyContext.jsx
// exported for when you really want to use useContext();
export const MyContext = React.createContext();
// Provides values to the consumer
export function MyContextProvider(props){
const [state, setState] = React.useState();
const [otherValue, setOtherValue] = React.useState();
return <MyContext.Provider value={{state, setState, otherValue, setOtherValue}} {...props} />
}
// HOC that provides the value to the component passed.
export function withMyContext(Component){
<MyContext.Consumer>{(value) => <Component {...value} />}</MyContext.Consumer>
}
// MyComponent.jsx
const MyComponent = ({state}) => {
// do something with state
}
// compares stringified state to determine whether to render or not. This is
// specific to this component because we only care about when state changes,
// not otherValue
const areEqual = ({state:prev}, {state:next}) =>
JSON.stringify(prev) !== JSON.stringify(next)
// wraps the context and memo and will prevent unnecessary
// re-renders when otherValue changes in MyContext.
export default React.memo(withMyContext(MyComponent), areEqual)
将上下文作为 props 传递而不是在渲染中使用它允许我们使用 areEqual 隔离我们实际关心的变化值。无法在渲染期间进行此比较useContext
.
我非常提倡将选择器作为第二个参数,类似于react-redux的新钩子useSelector。这将使我们能够做类似的事情
const state = useContext(MyContext, ({state}) => state);
Who的返回值只会在状态改变时改变,而不是整个上下文改变。
但我只是一个梦想家。
这可能是我现在对于在简单应用程序中使用 React-redux 而不是 hooks 的最大争论。