You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React函数组件setState更新失效 无法向Navbar传props问题

问题根因与修复方法

你这代码里有几个叠加的写法错误,才会导致状态看起来没更新,逐个改就行:

  • 最严重的错误:你把旧版React的ReactDOM.render渲染调用直接写在了App函数组件的内部。函数组件每一次渲染都会完整执行一遍整个函数体,你把根节点渲染逻辑塞在这里,会直接打乱React的状态更新和重渲染流程,状态修改后根本没法按预期触发视图更新。

    记住:render(或者React18的createRoot渲染逻辑)是写在组件外部的入口文件(一般是index.js)里的,函数组件本身只需要通过return返回需要渲染的JSX结构,绝对不要在组件内部调用render方法。

  • 第二个错误:useEffect没有传依赖数组。这种写法会导致组件每次渲染完成后都执行effect里的逻辑,而effect里调用了setUserData又会触发新的重渲染,直接进入死循环。你这段读localStorage解码JWT的逻辑只需要在组件第一次挂载的时候执行一次,给useEffect传个空数组[]当依赖就行。
  • 第三个错误:你在setUserData(user)执行后立刻打印emp1拿到的是null,这不是状态没更新,是React状态的异步更新+闭包特性导致的:setState调用后不会同步修改当前函数作用域里的userData变量,这个变量的值在当前这次渲染周期里是固定的,要等下一次组件重渲染的时候才能拿到更新后的值,这个位置的日志打出来null完全是正常现象。
  • 第四个错误:catch块是空的,如果localStorage里没有存token、或者JWT格式非法解码失败,错误会被直接吞掉,你根本没法排查是不是解码环节就出问题了。

修正后的代码

首先是入口文件index.js的正确写法,把路由、ToastContainer、根渲染逻辑都挪到这里:

import React from 'react';
import ReactDOM from 'react-dom/client';
import { BrowserRouter } from 'react-router-dom';
import { ToastContainer } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';
import App from './App';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <BrowserRouter>
    <ToastContainer
      rtl
      position="top-left"
      style={{ width: 520, fontSize: 15 }}
    />
    <App />
  </BrowserRouter>
);

然后是修复后的App.js:

import { useState, useEffect } from 'react';
import jwtDecode from 'jwt-decode';
import Navbar from './Navbar';

export default function App() {
  const [userData, setUserData] = useState(null);

  useEffect(() => {
    try {
      const jwt = localStorage.getItem("token");
      if (!jwt) return;
      const user = jwtDecode(jwt);
      console.log("解码得到的用户信息:", user);
      setUserData(user);
    } catch (ex) {
      console.error("Token解析失败:", ex);
    }
  }, []); // 空数组依赖,仅挂载时执行一次

  console.log("当前渲染周期的userData:", userData);

  return (
    <div className="App">
      <Navbar userData={userData} />
    </div>
  );
}

补充说明

组件第一次渲染的时候userData必然是初始值null,这是正常现象,等effect执行完调用setUserData触发第二次重渲染时,Navbar组件就能拿到正确的用户数据了。如果不想让Navbar首次渲染接收到null,可以加个简单的加载判断,等userData解析完成后再渲染Navbar组件。

内容的提问来源于stack exchange,提问作者HassanJalali

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 21:21:23