【问题标题】:ReactJS Change Sibling State via ParentReactJS 通过父更改兄弟状态
【发布时间】:2021-06-02 14:04:15
【问题描述】:

我的 React 结构是

- App
   |--SelectStudy
   |--ParticipantsTable

SelectStudy 中有一个按钮,单击该按钮会触发向其兄弟ParticipantsTable 发送消息,通过App 父级。第一个 Child->Parent 转移有效。但是如何实现第二个 Parent->Child transfer?请参阅 cmets 中的问题。

应用程序

class App extends Component { 

  myCallback(dataFromChild) {
      // This callback receives changes from SelectStudy Child Component's button click
      // THIS WORKS
      alert('SelectStudy Component sent value to Parent (App): ' + dataFromChild.label + " -> " + dataFromChild.value);
      // QUESTION: How to Update State of ParticipantsTable (SelectStudy's Sibling) next?
      // ........................................................
  }

  render() {
      return (
          <div className="App">
             <SelectStudy callbackFromParent={this.myCallback}></SelectStudy>
             <ParticipantsTable></ParticipantsTable>
          </div>
      );
}

选择研究

class SelectStudy extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            error: null,
            isLoaded: false,
            items: [],
            selectedStudy: null, 
            isButtonLoading: false
        };
        this.handleButtonClick = this.handleButtonClick.bind(this);
    }

    render() {
        const { error, isLoaded, items, itemsForReactSelect, selectedStudy, isButtonLoading } = this.state;
        return <Button onClick={this.handleButtonClick}>Search</Button>;
    }

    handleButtonClick = () => {
        this.props.callbackFromParent(this.state.selectedStudy);
    }

}

ParticipantsTable - 这需要接收某个变量,例如study 在其状态

class ParticipantsTable extends React.Component {
    constructor(props) {
        //alert('Constructor');
        super(props);
        // Initial Definition of this component's state
        this.state = {
            study: null,
            items: [], 
            error: null
        };
    }

    // THIS METHOD IS AVAILABLE, BUT HOW TO CALL IT FROM App's myCallback(dataFromChild)?
    setStudy = (selectedStudy) => {
        this.setState({study: selectedStudy});
    }    

    render() {
        return ( <div>{this.state.study}</div> );
    }
}

【问题讨论】:

  • 这是一个经典的反模式,为什么不将两个事物的状态存储在 App 中并向下传递 props。简单的解决方案

标签: reactjs


【解决方案1】:

我想你需要了解的是stateprops之间的区别。

state 在组件内部,而 props 从父级传递给子级

这是in-depth answer

所以您想在父级中设置一个state,您可以将其作为props 传递给子级

1 在父级中设置状态

 this.state = {
  value: null
 }

 myCallback(dataFromChild) {
    this.setState({value: dataFromChild.value})

  }

2 将它作为道具传递给孩子们

class ParticipantsTable extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            study: props.study,
            items: [], 
            error: null
        };
    }

此外,虽然与您的问题无关,但如果您学习 React,我建议您放弃基于类的组件,转而使用钩子和函数式组件,因为它们最近变得更广泛使用和流行。

【讨论】:

    【解决方案2】:

    状态应该明确存在于App 级别,而不是子级。状态需要比需要访问它的最低公分母高出一级。因此,如果SelectStudyParticipantsTable 都需要访问同一位状态数据,那么它必须生活在它们最近的共同祖先(或更高)中。

    这是 React 的一个核心概念,被称为“提升状态”,以至于它在 official React documentation. 中有自己的页面

    在你的情况下,它看起来像这样。请注意,状态如何只存在于一个地方,即&lt;App /&gt; 级别,并通过道具传递给孩子。

    import React from 'react';
    
    class App extends React.Component {
      // State lives here at the closest common ancestor of children that need it
      state = {
        error: null,
        isLoaded: false,
        items: [],
        selectedStudy: null,
        isButtonLoading: false
      };
    
      myCallback = (dataFromChild) => {
        this.setState(dataFromChild);
      };
    
      render() {
        return (
          <div className="App">
            {/* State is passed into child components here, as props */}
            <SelectStudy data={this.state} callbackFromParent={this.myCallback}></SelectStudy>
            <ParticipantsTable study={this.state.selectedStudy} />
          </div>
        );
      }
    }
    
    class SelectStudy extends React.Component {
      handleButtonClick = () => {
        // Here we execute a callback, provided by <App />, to update state one level up
        this.props.callbackFromParent({ ...this.props.selectedStudy, isButtonLoading: true });
      };
    
      render() {
        const { error, isLoaded, items, itemsForReactSelect, selectedStudy, isButtonLoading } = this.props.data;
    
        return <Button onClick={this.handleButtonClick}>Search</Button>;
      }
    }
    
    // This component doesn't need to track any internal state - it only renders what is given via props
    class ParticipantsTable extends React.Component {
      render() {
        return <div>{this.props.study}</div>;
      }
    }
    

    【讨论】:

    • 此方法需要注意的一件事是,对父级的每个状态更新都会重新渲染所有子级。有时(在这种情况下)可能是必要的。
    猜你喜欢
    • 1970-01-01
    • 2019-12-20
    • 2017-07-28
    • 2016-10-02
    • 2020-01-08
    • 2016-11-03
    • 2018-10-08
    • 2017-12-01
    • 2018-07-08
    相关资源
    最近更新 更多