为什么在下面的伪代码示例中,当容器更改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仍然显示旧值。


当前回答

我有同样的问题的重新渲染对象道具,如果道具是一个对象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对象在运行时改变了它的值,子组件将正确地重新呈现它。

其他回答

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

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

export default connect(mapStateToProps)(ChannelItem);

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

我也有同样的问题。 这是我的解决方案,我不确定这是一个好的实践,如果不是告诉我:

state = {
  value: this.props.value
};

componentDidUpdate(prevProps) {
  if(prevProps.value !== this.props.value) {
    this.setState({value: this.props.value});
  }
}

UPD:现在你可以用React Hooks做同样的事情: (仅当component是函数时)

const [value, setValue] = useState(propName);
// This will launch only if propName value has chaged.
useEffect(() => { setValue(propName) }, [propName]);

你可以使用componentWillReceiveProps:

componentWillReceiveProps({bar}) {
    this.setState({...this.state, bar})
}

这要归功于Josh Lunsford

根据React的理念,组件不能改变它的道具。它们应该从父进程接收,并且应该是不可变的。只有父节点可以更改其子节点的道具。

关于国家和道具的解释很好

另外,阅读这篇文章为什么我不能在react.js中更新道具?

在我的例子中,我正在更新传递给组件的加载状态。在按钮内的道具。加载是通过预期的(从假切换为真),但显示旋转器没有更新的三元。

我尝试添加一个键,添加一个状态,更新useEffect()等,但没有其他答案工作。

对我有效的是改变这一点:

setLoading(true);
handleOtherCPUHeavyCode();

:

setLoading(true);
setTimeout(() => { handleOtherCPUHeavyCode() }, 1)

我认为这是因为handleOtherCPUHeavyCode中的进程非常繁重和密集,所以应用程序会冻结一秒钟左右。添加1ms超时允许加载布尔值更新,然后繁重的代码函数可以完成它的工作。