React在SetState后不刷新子组件的解决方法

React 是一套组件化的前端 JavaScript UI 框架,每个组件可以声明并维护 state 属性,框架根据 state 的变化刷新组件。本文中,将父组件的 state 传递给子组件后,state 发生变化,子组件却没有更新。

问题

将本组件的 state 以 props 形式传递给子组件后,子组件用其值初始化自己的 state 。之后,当父组件 state 发生变化时,子组件并不会更新。

//反面教材,如果你不知道为什么这样写,就不要这么写
//再次提醒:反面教材,如果你不知道为什么这样写,就不要这么写
class A extends React.Component{
    constructor(props){
        super(props);
        this.state = {
            test:"t1";
        }
    }
    render(){
        return(
            <div>
                <B testVal={this.state.test} />
                //其他代码等
            </div>
        )
    }
    someCallBackFunc(str){
        this.setState({
            test:str
        })
    }
}

class B extends React.Component{
    constructor(props){
        super(props);
        //再再次提醒:反面教材,如果你不知道在写什么,就不要写
        this.state = {
            //反面教材,除特殊需求,尽量避免copying props into state。
            testVal:this.props.testVal;
        }
    }
    render(){
        return(
            <div>{this.state.testVal}</div>
        )
    }
}

当组件 A 内的someCallBackFunc方法被调用后,test 会在下一周期内更新为 str,但是 A 中渲染的子组件 B 却没有更新。

原因

排除这种情况:数组等对象,直接修改原对象,之后浅拷贝赋值,导致指针所指的内存地址没有改变, React 认为值没变。我的例子里是字符串,每次都会开辟一个新内存块,可以排除这种情况。

那原因是什么呢?很简单,官方文档里有说明:

Avoid copying props into state!
The problem is that it’s both unnecessary (you can use this.props.color directly instead),
and creates bugs (updates to the color prop won’t be reflected in the state).
Only use this pattern if you intentionally want to ignore prop updates.
In that case, it makes sense to rename the prop to be called initialColor or defaultColor.
You can then force a component to “reset” its internal state by changing its key when necessary.

实际上,造成不更新的原因就是 B 组件中的testVal是一直不变的,其值为首次初始化时的值,也就是最开始的props.testVal

换句话说,在构造函数constructor或者getInitialState执行后,这个值就不变了。

根据开发规范,把 props 参数拷贝成 state 是不合理的,除非想忽略 props 的更新,例如默认颜色等特殊情况

解决方法

  1. 直接使用this.props.testVal
    将 B 的 Render 内容修改为:

    render(){
            return(
                <div>{this.props.testVal}</div>
            )
        }
    
  2. 重写 props 变化回调(不推荐)
    在 B 中重写方法 componentWillReceiveProps

    componentWillReceiveProps(nextProps){
        this.setState({
            testVal:nextProps.testVal
        });
    }
    

    该方法会在 props 发生变更时调用,可以在此时更新 state。

梓喵出没博客(azimiao.com)版权所有,转载请注明链接:https://www.azimiao.com/6316.html
欢迎加入梓喵出没博客交流群:313732000

回复 davont

*

*

评论区

  1. 虾米02-01 15:26 回复

    谢谢!有帮助

  2. davont02-22 16:42 回复

    “把 props 参数拷贝成 state 是不合理的,除非想忽略 props 的更新,例如默认颜色等特殊情况。”
    如果这个props是用react-redux 插件的话,在state中设置props值其实是可以的。(一个小补充)