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

如何从React子组件更新父组件状态?附组件重构方案

问题描述

我在React页面中写了这段代码:

<a
    data-tab="settings"
    onClick={() =>
        this.setState({ active_tab: "settings" })
    }
>
    <i style={{ backgroundImage: "url(/icons/settings.svg)" }} />
    <span>To settings</span>
</a>

想知道怎么把这段代码重构为组件,以及如何通过该组件更新父组件的本地状态。


一、基于类组件的实现

组件文件(MyButton.js)

import React, { Component } from "react";

class MyButton extends Component {
    constructor(props) {
        super(props);
        this.state = {
            tab: props.tab,
            icon: props.icon,
            label: props.label,
        };
    }

    render() {
        return (
            <div>
                <button
                    onClick={() => this.props.updateActiveTab(this.state.tab)}
                    data-tab={this.state.tab}
                >
                    <i style={{ backgroundImage: `url(${this.state.icon})` }} />
                    <span> { this.state.label } </span>
                </button>
            </div>
        )
    }
};

export default MyButton;

父组件(React页面)

import MyButton from "../components/MyButton/";

class MyReactPage extends Component {
    updateActiveTab = value => {
        this.setState({ active_tab: value });
    }

    render() {
        return (
            <>
                <MyButton
                    updateActiveTab={this.updateActiveTab}
                    tab="settings"
                    icon="/icons/settings.svg"
                    label="To settings"
                />
            </>
        )
    }
}

二、基于React Hooks的实现及错误修正

原Hooks方案存在两个错误:

  • Invalid hook call. Hooks can only be called inside of the body of a function component. → 钩子调用无效。钩子只能在函数组件的主体内部调用。
  • 'active_tab' is declared but its value is never read. → 'active_tab'已声明但从未被使用。

错误原因及修正后的代码

  1. 原组件接收props的方式错误,函数组件的props是一个整体对象,需通过解构或props.xxx获取;
  2. 子组件无需维护active_tab状态,应通过父组件传入的回调函数更新父组件状态;
  3. 父组件调用函数组件的方式错误,需用<MyButton />标签形式,而非直接调用函数。

修正后的组件文件(MyButton.js)

import React from "react";

const MyButton = (props) => {
    const { tab, icon, label, onTabChange } = props;
    return (
        <button
            data-tab={tab}
            onClick={() => onTabChange(tab)}
        >
            <i style={{ backgroundImage: `url(${icon})` }} />
            <span> { label } </span>
        </button>
    );
};

export default MyButton;

修正后的类父组件(React页面)

import React, { Component } from "react";
import MyButton from "../components/MyButton/";

class MyReactPage extends Component {
    updateActiveTab = value => {
        this.setState({ active_tab: value });
    }

    render() {
        return (
            <>
                <MyButton
                    onTabChange={this.updateActiveTab}
                    tab="settings"
                    icon="/icons/settings.svg"
                    label="To settings"
                />
            </>
        )
    }
}

父组件也用Hooks实现的版本

import React, { useState } from "react";
import MyButton from "../components/MyButton/";

const MyReactPage = () => {
    const [activeTab, setActiveTab] = useState("");

    const handleTabChange = (tabValue) => {
        setActiveTab(tabValue);
    };

    return (
        <>
            <MyButton
                onTabChange={handleTabChange}
                tab="settings"
                icon="/icons/settings.svg"
                label="To settings"
            />
        </>
    )
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 00:21:25