为什么在下面的伪代码示例中,当容器更改foo.bar时,子不重新呈现?

Container {
  handleEvent() {
    this.props.foo.bar = 123
  },

  render() {
    return <Child bar={this.props.foo.bar} />
}

Child {
  render() {
    return <div>{this.props.bar}</div>
  }
}

即使我在修改Container中的值后调用forceUpdate(), Child仍然显示旧值。


当前回答

确认,添加一个密钥工作。我看了所有的文件想弄清楚原因。

React希望在创建子组件时高效。如果新组件与另一个子组件相同,它就不会呈现新组件,这使得页面加载更快。

添加Key会迫使React呈现新组件,从而重置新组件的状态。

https://reactjs.org/docs/reconciliation.html#recursing-on-children

其他回答

你必须使用动态组件。

在这个代码片段中,我们多次渲染子组件并传递key。

如果我们动态渲染一个组件多次,那么React不会渲染该组件,直到它的键被更改。

如果我们使用setState方法更改检查。它不会反映在子组件中,直到我们改变它的键。我们必须在child的状态上保存它然后相应地将它改为渲染child。

类父扩展组件{ 状态= { 检查:真 } 呈现(){ 回报( < div className =“父”> { [1,2,3].map( N => <div key={N}> <孩子完成= {this.state。检查}/ > < / div > ) } < / div > ); } }

你应该使用setState函数。如果不是,无论如何使用forceUpdate, state都不会保存您的更改。

Container {
    handleEvent= () => { // use arrow function
        //this.props.foo.bar = 123
        //You should use setState to set value like this:
        this.setState({foo: {bar: 123}});
    };

    render() {
        return <Child bar={this.state.foo.bar} />
    }
    Child {
        render() {
            return <div>{this.props.bar}</div>
        }
    }
}

你的代码似乎无效。我不能测试这段代码。

我有同样的问题的重新渲染对象道具,如果道具是一个对象JSON.stringify(obj),并将其设置为功能组件的关键。为react钩子设置一个id键对我来说并不适用。奇怪的是,要更新组件,你必须在键上包含所有对象属性并将其连接到那里。

function Child(props) {
  const [thing, setThing] = useState(props.something)
  
  return (
   <>
     <div>{thing.a}</div>
     <div>{thing.b}</div>
   </>
  )
}

...

function Caller() {
   const thing = [{a: 1, b: 2}, {a: 3, b: 4}]
   thing.map(t => (
     <Child key={JSON.stringify(t)} something={thing} />
   ))
}

现在,任何时候thing对象在运行时改变了它的值,子组件将正确地重新呈现它。

因为如果父对象的道具改变了,子对象不会重新渲染,但是如果它的STATE改变了:)

你所展示的是: https://facebook.github.io/react/tips/communicate-between-components.html

它将通过道具将数据从父对象传递到子对象,但没有渲染逻辑。

你需要为父节点设置一些状态,然后在父节点更改状态上重新渲染子节点。 这可能会有所帮助。 https://facebook.github.io/react/tips/expose-component-functions.html

在子组件connect方法的mapStateToProps中定义更改的道具。

function mapStateToProps(state) {
  return {
    chanelList: state.messaging.chanelList,
  };
}

export default connect(mapStateToProps)(ChannelItem);

在我的例子中,channelList的通道被更新了,所以我在mapStateToProps中添加了chanelList