react接收到新的props时,怎么重新渲染

父组件更新子组件的props,在子组件接收到新的props时,需要更新子组件的state,但是却没有重新渲染。我想在componentWillReceiveProps方法中更新子组件的state,但是却没有重新渲染。
官网上有这么一句话:

在该函数中调用 this.setState() 将不会引起第二次渲染。

如果不重新渲染,那么获取到的新数据怎么更新到视图上去?

阅读 44.6k
7 个回答

子组件显示父组件穿过来的props有两种方式:

1、直接使用

这种方式,父组件改变props后,子组件重新渲染,由于直接使用的props,所以我们不需要做什么就可以正常显示最新的props

class Child extends Component {
    render() {
        return <div>{this.props.someThings}</div>
    }
}

2、转换成自己的state

这种方式,由于我们使用的是state,所以每当父组件每次重新传递props时,我们需要重新处理下,将props转换成自己的state,这里就用到了 componentWillReceiveProps

关于你提到的不会二次渲染是这样的:每次子组件接收到新的props,都会重新渲染一次,除非你做了处理来阻止(比如使用:shouldComponentUpdate),但是你可以在这次渲染前,根据新的props更新state,更新state也会触发一次重新渲染,但react不会这么傻,所以只会渲染一次,这对应用的性能是有利的。

class Child extends Component {
    constructor(props) {
        super(props);
        this.state = {
            someThings: props.someThings
        };
    }
    componentWillReceiveProps(nextProps) {
        this.setState({someThings: nextProps.someThings});
    }
    render() {
        return <div>{this.state.someThings}</div>
    }
}

谢邀回答!

Use this as an opportunity to react to a prop transition before render() is called by updating the state using this.setState(). The old props can be accessed via this.props. Calling this.setState() within this function will not trigger an additional render.

用此函数可以作为 react 在 prop 传入之后, render() 渲染之前更新 state 的机会。老的 props 可以通过 this.props 获取到。在该函数中调用 this.setState() 将不会引起第二次渲染。

贴上英文文档和中文社区翻译的文档,说的清楚:在render之前可以更新state,不会引起第二次渲染并不是说不渲染.碰到这种情况,自己写个简单demo试试不就知道了?在附上测试代码

class Child extends Component {
    constructor(props) {
        super();
        this.state = {
            text: props.text
        }
    }

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

    render() {
        return <p>{this.state.text}</p>
    }
}

class Parent extends Component {
    state = {
        name: 'xxx'
    }

    render() {
        return (
            <div>
                <Child text={this.state.name}/>
                <button onClick={() => this.setState({name: 'zzz'})}>change</button>
            </div>
        )
    }
}

先说下你的 prop 的格式,和在 componentWillReceiveProps 里怎么做的吧,另,有没有写 shouldComponentUpdate。
setState 不会引发的是 第二次渲染,也就是说进入 componentWillReceiveProps 就已经是第一次渲染了,如果在其他生命周期里调用,还会引发第二次渲染,但是 componentWillReceiveProps 里不会

1: componentWillReceiveProps里setState你想改变的数据
2: 视图中引用该数据
是可以更新的

新手上路,请多包涵

这里说的不会造成第二次的渲染,并不是说这里的setState不会生效。在这个方法里调用setState会在组件更新完成之后在render方法执行之前更新状态,将两次的渲染合并在一起。可以在componentWillReceiveProps执行setState,但是如果你想在这个方法里获取this.state得到的将会是上一次的状态。

你的store 监听没有啊
subscribe

新手上路,请多包涵

永远不要在 constructor 里使用props初始化state值,不然就会导致这个问题;要么直接用props渲染,要么使用新的生命周期函数

class Child extends Component {
    state = { text: '' };

    //getDerivedStateFromProps is invoked right before calling the render method, both on the initial mount and on subsequent updates. It should return an object to update the state, or null to update nothing.
    static getDerivedStateFromProps(props) {
        return {
            text: props.text
        };
    }

    render() {
        return <p>{this.state.text}</p>
    }
}

class Parent extends Component {
    state = {
        name: 'xxx'
    }

    render() {
        return (
            <div>
                <Child text={this.state.name}/>
                <button onClick={() => this.setState({name: 'zzz'})}>change</button>
            </div>
        )
    }
}
推荐问题
宣传栏