【问题标题】:ReactJS: Mutating child state from parent via propsReactJS:通过道具从父级改变子状态
【发布时间】:2016-11-03 06:39:37
【问题描述】:

免责声明:我查看了Reactjs: how to modify child state or props from parent?,但不相信答案适合我的问题。

所以我有一个可重用的、有状态的对话组件,它根据其状态呈现不同的 DOM。我还必须能够控制从父级渲染哪个 DOM。

TL;DR - 我应该如何改变父组件的子组件状态,如果有的话,还有哪些其他选项?

孩子:

export default class Conversation extends Component {
  constructor(props) {
    super(props);
    
    this.state = {
      newConversation: props.showNewConversation
    };
  }
  
  render() {
   if (!this.state.newConversation) {
    return (
      <div>Current Conversation</div>
    );
   } return (
      <div>New Conversation</div>
    );
  }
}

现在我需要在不同的地方渲染这个组件,但是我需要根据父级渲染适当的 DOM,即从导航栏你可以创建一个新的对话,从用户页面你可以直接进入你的对话和他们在一起,所以我可以控制何时通过它的道具给孩子打电话。

通过 prop 调用 child 并设置 state:

<Conversation
  showNewConversation={this.state.isConversationShown === true}
/>

这目前正在运行,但有人告诉我这是 React 中的一个非常糟糕的做法,我的问题实际上是为什么这被认为是不好的做法,以及一个好的做法解决方案是什么样的。

【问题讨论】:

  • 为什么对于通过props从所有者到拥有组件的数据流来说这是一个非常糟糕的做法?

标签: javascript reactjs react-jsx


【解决方案1】:

在 React 中,一般的最佳实践是尽可能使尽可能多的组件“无状态”。通常,如果您没有加载异步数据或正在接受用户输入,则不需要状态。

在这个例子中,主要问题发生如下:如果父渲染

<Conversation newConversation={true} />

稍后将其重新渲染为

<Conversation newConversation={false} />

然后孩子将不会按预期呈现,因为 React 将“更新”孩子对话(重新渲染)但不会再次调用构造函数。因为你只是在构造函数中将 props 传递给 state,所以 child 永远不会改变。

大多数组件应该仅作为其属性的函数进行渲染。您的孩子可以适应以下情况:

export default class Conversation extends Component {
  constructor(props) {
    super(props);
  }

  render() {
   if (!this.props.newConversation) {
    return (
      <div>Current Conversation</div>
    );
   } return (
      <div>New Conversation</div>
    );
  }
}

这里,父级的更新将允许子级正确地重新渲染,因为您直接引用了子级的 render() 函数中的道具。

如果您有更多关于正在呈现的对话的数据,那么您应该将所有数据作为道具传递。即

<Conversation conversationData={{name: 'abc', new: false}} />

那么Conversation组件就可以直接在render()方法中访问props了。

如果你绝对必须改变状态,那么它应该是由 parent 改变 props 的形式:

export default class Conversation extends Component {
  constructor(props) {
    super(props);

    this.state = {
      newConversation: props.showNewConversation
    };
  }

  // Response to change
  componentWillReceiveProps(nextProps){
      this.setState({newConversation: this.props.showNewConversation});

  }

  render() {
   if (!this.state.newConversation) {
    return (
      <div>Current Conversation</div>
    );
   } return (
      <div>New Conversation</div>
    );
  }
}

【讨论】:

  • 很棒的答案!将其从状态中取出并仅作为对话的道具进行拉扯是一种享受并且更清洁。非常感谢!
猜你喜欢
  • 2014-10-09
  • 1970-01-01
  • 1970-01-01
  • 2019-10-04
  • 2016-09-18
  • 2018-11-08
  • 2021-06-02
  • 2015-04-15
  • 2015-12-02
相关资源
最近更新 更多