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

React报错:无法在未挂载的组件上调用setState

解决React组件中“无法在未挂载的组件上调用setState”错误及数据显示问题

问题描述

开发React组件时遇到报错:无法在未挂载的组件上调用setState,跟随Udemy教程操作但未出现该错误。怀疑是React Router v5与v6版本差异导致,但未找到解决方案。需求是点击用户名或搜索用户名时拉取指定GitHub用户数据,但当前所有this.state调用都无法正常显示结果。

错误原因

  1. 异步请求时机错误:在constructor中发起异步请求并调用setState,组件尚未完成挂载就触发状态更新,若组件在请求完成前被卸载,就会触发报错。
  2. GitHub API路径错误:使用了搜索用户列表的接口https://api.github.com/search/users/${user},返回的是包含用户数组的对象,而非单个用户数据,导致后续状态处理异常。
  3. 初始状态与判断逻辑错误:初始user设为数组[],后续判断this.state.user.login===0逻辑不合理,且数组访问login会引发错误。
  4. React Router参数传递问题:v6中已移除withRouter高阶组件,自定义的withRouter可能存在参数传递异常,导致props.params.login无法获取正确值。

修复步骤

  • 迁移异步请求到正确生命周期:将请求移至componentDidMount,确保组件挂载后再发起请求,同时在componentWillUnmount中设置标记,防止组件卸载后更新状态。
  • 修正GitHub API接口:改用单个用户查询接口https://api.github.com/users/${user},直接获取目标用户的完整数据。
  • 调整状态初始化与判断逻辑:初始user设为null,通过判断user是否为空或是否存在错误信息来展示对应内容,同时添加加载状态提示。
  • 适配React Router v6(可选):若使用v6,推荐用useParams钩子,类组件可通过包装为函数组件传递参数,确保login参数正确获取。

完整修复代码

import React, { Component } from "react";
import withRouter from '../withRouter';
import Repose from "./Repose";

class Specific extends Component {
    constructor(props) {
        super(props);
        this.state = { user: null, error: null };
        this._isMounted = false; // 标记组件是否挂载
    }

    componentDidMount() {
        this._isMounted = true;
        this.fetchUser(this.props.params.login);
    }

    componentWillUnmount() {
        this._isMounted = false; // 组件卸载时更新标记
    }

    fetchUser = async (user) => {
        try {
            const apiCall = await fetch(`https://api.github.com/users/${user}`);
            if (!apiCall.ok) throw new Error('User not found');
            const data = await apiCall.json();
            
            // 仅在组件挂载时更新状态
            if (this._isMounted) {
                this.setState({ user: data, error: null });
            }
        } catch (err) {
            if (this._isMounted) {
                this.setState({ error: err.message, user: null });
            }
        }
    }

    renderData() {
        const { user, error } = this.state;
        const { login } = this.props.params;

        if (error) return <i>No user with given username: {login}</i>;
        if (!user) return <i>Loading...</i>;

        return (
            <center>
                <section className="Specific">
                    <div className="main" id="main">
                        <div className="container">
                            <div className="row">
                                <div className="col-lg-12 col-md-12">
                                    <div className="SUsersData">
                                        <i className="fas fa-heart NotFave"></i>
                                        <h4>Name : <i className="bl">{user.name || 'No name'}</i></h4>
                                        <img src={user.avatar_url} alt={`${user.login}'s avatar`} />
                                        <h4>followers : <i className="bl">{user.followers}</i></h4>
                                        <h4>location : <i className="bl">{user.location || 'No location'}</i></h4>
                                        <Repose user={login} />
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                </section>
            </center>
        );
    }

    render() {
        return (
            <React.Fragment>
                {this.renderData()}
            </React.Fragment>
        );
    }
}

export default withRouter(Specific);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 20:48:18