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

React父子组件传值异常:多次点击按钮后数值更新不符预期

父子组件传值异常问题分析

问题描述

父组件向子组件传递一个数值,子组件点击按钮后给该数值加3并传回父组件,父组件给传回的数值加100后,再传递给子组件。但实际运行时,第一次点击输出104,从第二次点击开始数值仅增加3,而非预期的每次增加103。

问题代码

class Parent2 extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            msgFromOut: props.out,
        };
    }

    getChildMsg = (data) => {
        console.log("get the msg from child component data is ", data);
        this.setState({
            msgFromOut: 100 + data,
        });
    };
    render() {
        return (
            <div className="parent">
                this is father
                <Child2 getMsg={this.getChildMsg} outerMsg={this.state.msgFromOut} />
                <h1>{this.state.msgFromOut}</h1>
            </div>
        );
    }
}

class Child2 extends React.Component {
    constructor(props) {
        super(props);
        console.log("child is getting", props);
        this.state = {
            msgFromFather: props.outerMsg,
        };
    }

    handleClick = () => {
        this.setState(
            {
                msgFromFather: this.state.msgFromFather + 3,
            },
            () => {
                this.props.getMsg(this.state.msgFromFather);
            }
        );
    };

    render() {
        return <button onClick={this.handleClick}>to father</button>;
    }
}

reactDom.render(<Parent2 out={1} />, document.querySelector("#root3"));

原因分析

  • 子组件Child2的msgFromFather状态只在构造函数中初始化了一次,后续父组件更新outerMsg传递新值时,子组件并没有同步更新自身的msgFromFather状态。
  • 第一次点击流程:父组件初始值1 → 子组件初始化msgFromFather为1 → 加3后变成4传给父组件 → 父组件加100得到104。此时父组件状态更新,但子组件的msgFromFather仍停留在4。
  • 第二次点击流程:子组件基于自身状态4加3得到7 → 传给父组件加100得到107,看起来只增加了3(104→107),本质是子组件没有用父组件最新传递的数值计算。

解决方案

有两种常见的解决方式:

方式一:子组件直接使用父组件props,不维护自身状态

既然子组件的数值完全依赖父组件传递的值,没必要单独维护状态,直接用props.outerMsg计算即可:

class Child2 extends React.Component {
    handleClick = () => {
        // 直接使用props中的最新值计算
        const newVal = this.props.outerMsg + 3;
        this.props.getMsg(newVal);
    };

    render() {
        return <button onClick={this.handleClick}>to father</button>;
    }
}

方式二:子组件监听props变化,同步更新自身状态

如果子组件必须维护自身状态,需要通过componentDidUpdate生命周期钩子监听props.outerMsg的变化,同步更新msgFromFather:

class Child2 extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            msgFromFather: props.outerMsg,
        };
    }

    // 监听props变化,同步更新子组件状态
    componentDidUpdate(prevProps) {
        if (prevProps.outerMsg !== this.props.outerMsg) {
            this.setState({
                msgFromFather: this.props.outerMsg
            });
        }
    }

    handleClick = () => {
        this.setState(
            {
                msgFromFather: this.state.msgFromFather + 3,
            },
            () => {
                this.props.getMsg(this.state.msgFromFather);
            }
        );
    };

    render() {
        return <button onClick={this.handleClick}>to father</button>;
    }
}

修改后,每次父组件传递新值,子组件都会同步更新,点击按钮时就能基于最新数值计算,实现每次点击增加103的预期效果。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 18:05:23