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


当前回答

更新子进程以使属性'key'与名称相等。每次键改变时,组件都会重新呈现。

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

其他回答

考虑到道具的渲染限制和状态的增益,如果你使用反应钩子,你可以使用一些技巧。例如,您可以使用useEffect手动将道具转换为状态。这可能不是最好的做法,但在这些情况下是有帮助的。

import { isEqual } from 'lodash';
import { useEffect, useState } from 'react';

export const MyComponent = (props: { users: [] }) => {
  const [usersState, setUsersState] = useState([]);

  useEffect(() => {
    if (!isEqual(props.users, usersState)) {
      setUsersState(props.users);
    }
  }, [props.users]);

  <OtherComponent users={usersState} />;
};

如果Child不维护任何状态,而只是呈现道具,然后从父组件调用它,那么您可能应该将它作为功能组件。除此之外,您还可以使用与功能组件(useState)的挂钩,这将导致无状态组件重新呈现。

此外,您不应该更改propas,因为它们是不可变的。维护组件的状态。

Child = ({bar}) => (bar);

你必须使用动态组件。

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

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

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

类父扩展组件{ 状态= { 检查:真 } 呈现(){ 回报( < div className =“父”> { [1,2,3].map( N => <div key={N}> <孩子完成= {this.state。检查}/ > < / div > ) } < / 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对象在运行时改变了它的值,子组件将正确地重新呈现它。

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

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

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