【问题标题】:Best practice way to set state from one component to another in React在 React 中将状态从一个组件设置为另一个组件的最佳实践方法
【发布时间】:2019-04-01 18:59:37
【问题描述】:

我是从最佳实践的角度提出这个问题 - 我在这里找到的答案是针对单个代码库的更具体的问题。如果它已经被回答,我很高兴被指出正确的方向,或者如果我正在尝试的不是好的做法,我很高兴能以另一种方式展示 - 我可能误解了一些概念......

我正在学习 React,并正在使用它构建一个简单的应用程序。 主要是为了保持我的代码整洁,我创建了两个文件。 第一个文件 - 我从我的组件内部访问一个 API,并从我的组件状态呈现一些数据。 第二个文件 - 我想在我的第一个文件中使用来自组件状态的相同信息,并将其用作我的第二个文件中的道具。

下面是一个简化的例子。

第一个文件:

import React, { Component } from 'react';
import SecondComponent from './SecondComponent';

function DisplayFirstData (props) {
  return (
    {props.data}
}

class FirstComponent extends Component {
  constructor(props) {
    super(props);
    this.state = {
      myData: something,
    }
  }
  render() {
    <DisplayFirstData data={this.state.myData} />
  }
}

第二部分:

import React, { Component } from 'react';

function DisplaySecondData (props) {
  return (
    {props.data}
}

class SecondComponent extends Component {
  constructor(props) {
    super(props);
    this.state = {
      // State object from the first component file
    }
  }
  render() {
    <DisplaySecondData data={this.state.myData} />
  }
}

【问题讨论】:

  • Redux 就是答案。 redux.js.org
  • 为什么你有两个叫App的组件?
  • 一种常见的技术是 lift state up to the first common ancestor 两个组件,并将其作为道具传递给两者。
  • @Tholle - 谢谢,这听起来合乎逻辑且易于维护,我会调查一下
  • 首先,由于&lt;DisplayFirstData /&gt;&lt;DisplaySecondData /&gt; 做的事情完全一样,我建议你把它们放在一个文件中并命名为&lt;DisplayData /&gt;。每当您需要它时,只需将其导入您的 firstfile.jssecondfile.js

标签: javascript reactjs


【解决方案1】:

我不太确定您要完成什么,但我建议您做两件事:

  • 由于&lt;DisplayFirstData /&gt;&lt;DisplaySecondData /&gt; 执行完全相同的操作,您应该将它们移动到一个新文件并将其命名为&lt;DisplayData /&gt;(我说“它”是因为您最终只会得到一个组件)。每当您需要它时,只需:import DisplayData from 'path/to/file
  • 现在您有了&lt;DisplayData /&gt; 组件,将一个组件包裹在您的&lt;FirstComponent /&gt;&lt;SecondComponent /&gt; 周围,将其命名为&lt;ParentComponent /&gt;。将所有状态从 &lt;FirstComponent /&gt; 移动到 &lt;ParentComponent /&gt;。如果您的数据是在其他地方提取的,请同时移动提取代码。

之后,您只需将状态传递给&lt;FirstComponent /&gt;&lt;SecondComponent /&gt;。您可以直接在&lt;SecondComponent /&gt; 中将状态作为道具访问,或者您可以从道具初始化其状态。更多信息请阅读this

总体而言,您的代码应如下所示:

import React, { Component } from 'react';
import { FirstComponent, SecondComponent } from 'path/to/folder/contains/the/files';

class ParentComponent extends Component {
  state = {
    //Move your states here
  }
  //Move your fetching code here
  render() {
    const { data } = this.state; 
    return(
      <>
        <FirstComponent data={data} />
        <SecondComponent data={data} />
      </>
    );
  }
}

&lt;SecondComponent /&gt;:

import React from 'react';
import DisplayData from 'path/to/file';

export default SecondComponent = props => {
  const { data } = props.data;

  return(
    <DisplayData data={data} />
  )
}

【讨论】:

    【解决方案2】:

    一种常见的技术是 lift state up to the first common ancestor 两个组件,并将其作为道具传递给两者。

    示例

    function getData() {
      return new Promise(resolve => setTimeout(() => resolve(42), 1000));
    }
    
    class FirstComponent extends React.Component {
      render() {
        return <div>{this.props.data}</div>;
      }
    }
    
    class SecondComponent extends React.Component {
      render() {
        return <div>{this.props.data}</div>;
      }
    }
    
    class App extends React.Component {
      state = { data: null };
    
      componentDidMount() {
        getData().then(data => {
          this.setState({ data });
        });
      }
    
      render() {
        const { data } = this.state;
        
        if (data === null) {
          return null;
        }
        return (
          <div>
            <FirstComponent data={data} />
            <SecondComponent data={data} />
          </div>
        );
      }
    }
    
    ReactDOM.render(<App />, document.getElementById("root"));
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
    <div id="root"></div>

    【讨论】:

      【解决方案3】:

      正如 cmets 中所指出的,一种常见的技术是将状态提升到两个组件的第一个共同祖先,并将其作为 props 传递给两者。

      这是您的顶级(父)组件(用于保持您的状态的基于类的组件),然后通过道具将该数据传递给子项:

      import DisplayFirstData from "./DisplayFirstData";
      import DisplaySecondData from "./DisplaySecondData";
      
      class App extends Component {
        state = { myData: "something" };
        render() {
          return (
            <div>
              <DisplayFirstData data={this.state.myData} />
              <DisplaySecondData data={this.state.myData} />
            </div>
          );
        }
      }
      

      在其中,您将在 state 中初始化的数据通过 prop 数据传递给您正在调用 &lt;DisplayFirstData /&gt; 的第二个组件,&lt;DisplaySecondData /&gt; 也是如此

      这是您的子组件 1:

      const DisplayFirstData = props => (
        <div>
          <h2>Access your data here via props</h2>
          <p>{props.data}</p>
        </div>
      );
      
      export default DisplayFirstData;
      

      这是您的子组件 2:

      const DisplaySecondtData = props => (
        <div>
          <h2>Access your data here via props</h2>
          <p>{props.data}</p>
        </div>
      );
      
      export default DisplaySecondData;
      

      codeandbox 上的一个工作示例...:https://codesandbox.io/s/407oq1znx

      附带说明:我不知道为什么你需要 2 个不同的组件,它们基本上做同样的事情,但无论如何,上面的例子就是这样做的方法......另外,在你的学习之旅,你应该了解并爱上更高的order component patterncontext API(我怀疑随着你不断尝试构建它,你会需要它们......)

      【讨论】:

        猜你喜欢
        • 2020-10-03
        • 2019-02-26
        • 2020-11-23
        • 2016-06-05
        • 2021-01-11
        • 1970-01-01
        • 1970-01-01
        • 2021-01-02
        • 1970-01-01
        相关资源
        最近更新 更多