React调用useState报TypeError: Cannot read properties of null错误
报错根本原因
这个错误是React Hook执行上下文丢失导致的,结合错误堆栈里的express路由、服务端文件调用记录,你是在SSR(服务端渲染)场景下触发的问题,具体触发点:
- 服务端代码没有使用React官方提供的SSR渲染API,直接手动调用了
AppComponent()函数执行组件。这种写法完全绕过了React的渲染调度流程,React内部存储Hook状态的dispatcher对象为null,执行useState时读取属性就会抛出这个类型错误。 - 次要可能原因:项目依赖中存在多份React实例,或者webpack打包时对react、react-dom做了拆分导致实例不一致,Hook无法匹配到对应的React上下文。
- 你使用的
hot热更新高阶组件如果没有做SSR环境兼容,服务端渲染时也可能破坏组件的Hook调用链路。
修复步骤
按优先级依次排查修复:
- 修正服务端渲染逻辑
打开报错堆栈里提到的src/server/server.js文件,找到第14行附近调用App组件的位置,不要直接执行组件函数,必须用react-dom/server提供的渲染方法处理组件:
// 错误写法(你当前的写法) // const appContent = App() // 正确写法 import { renderToString } from 'react-dom/server' import { App } from '../App.tsx' const appContent = renderToString(<App />)
- 排查多React实例问题
在项目根目录执行命令检查是否存在重复版本的React依赖:
npm ls react npm ls react-dom
如果输出结果显示存在多个版本的react/react-dom,先删除node_modules目录和依赖锁文件(package-lock.json/yarn.lock/pnpm-lock.yaml),重新执行npm install安装依赖。如果还是存在多实例问题,在webpack配置中添加别名强制全局使用同一份React:
const path = require('path') module.exports = { resolve: { alias: { react: path.resolve(__dirname, 'node_modules/react'), 'react-dom': path.resolve(__dirname, 'node_modules/react-dom') } } }
- 兼容热更新的SSR场景
不要在服务端渲染时套用客户端热更新的高阶组件,增加环境判断,仅在客户端浏览器环境启用hot包裹:
function AppComponent() { const [token,setToken] = React.useState(''); React.useEffect(() => { console.log(window.__token__) if(window.__token__) { setToken(window.__token__); } },[]); const {Provider} = tokenContext; return( <Provider value={token}> <Layout> <Header /> <Content> <CardsList /> </Content> </Layout> </Provider> ); } // 仅客户端开发环境启用热更新 export const App = typeof window !== 'undefined' && process.env.NODE_ENV === 'development' ? hot(AppComponent) : AppComponent;
注意:React Hook 仅能在被React调度渲染的函数组件/自定义Hook顶层调用,手动直接执行组件函数属于错误用法,会导致所有Hook相关逻辑失效。
内容的提问来源于stack exchange,提问作者reik
相关产品推荐
相关产品推荐

