使用compose组合React Context的with函数后状态不更新,求排查
React Context状态无法更新问题排查
我尝试为每个React Context创建对应的with函数,再通过compose函数将它们组合成withProviders函数包裹App组件,但发现状态无法更新。请问哪里操作出错了?
代码示例
main.jsx
import React from "react"; import ReactDOM from "react-dom/client"; import App from "./App"; ReactDOM.createRoot(document.getElementById("root")).render( <React.StrictMode> <App /> </React.StrictMode> );
App.jsx
import { useAuth, withProviders } from "./withProviders"; function App() { const [authenticated, setAuthenticated] = useAuth(); const toggle = () => setAuthenticated((b) => !b); return ( <div className="App"> <div>{authenticated.toString()}</div> <button onClick={toggle}>toggle</button> </div> ); } export default withProviders(App);
withProviders.jsx
import { createContext, useContext, useState } from "react"; import compose from "compose-function"; const AuthContext = createContext([false, () => null]); const withAuth = (component) => { return function AuthProvider() { const [authenticated, setAuthenticated] = useState(false); return ( <AuthContext.Provider value={[authenticated, setAuthenticated]}> {component()} </AuthContext.Provider> ); }; }; export const useAuth = () => useContext(AuthContext); export const withProviders = compose(withAuth);
问题原因与修复方案
问题出在withAuth函数里的组件调用方式:直接执行component()而非以React组件形式渲染(<component />)。这种写法会让组件脱离React的上下文更新机制,状态变化时组件无法重新渲染,自然拿不到最新状态值。
修复后的withProviders.jsx
import { createContext, useContext, useState } from "react"; import compose from "compose-function"; const AuthContext = createContext([false, () => null]); const withAuth = (Component) => { return function AuthProvider(props) { const [authenticated, setAuthenticated] = useState(false); return ( <AuthContext.Provider value={[authenticated, setAuthenticated]}> <Component {...props} /> </AuthContext.Provider> ); }; }; export const useAuth = () => useContext(AuthContext); export const withProviders = compose(withAuth);
关键修改点:
- 将
component()改为<Component {...props} />,遵循React组件渲染规范,确保组件能响应上下文状态变化 - 组件参数名改为大写
Component(React组件命名惯例,避免与普通变量混淆) - 给
AuthProvider添加props参数并传递给子组件,保证组件能接收外部属性
修改后,当authenticated状态变化时,Context Provider会通知App组件重新渲染,状态更新即可正常生效。
内容的提问来源于stack exchange,提问作者mukkumayc
相关产品推荐
相关产品推荐

