在 React 中将状态从一个组件设置为另一个组件的最佳实践方法

IT技术 javascript reactjs
2021-05-16 01:53:49

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

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

下面是一个简化的例子。

第一个文件:

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} />
  }
}
3个回答

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

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

之后,您只需要将状态传递给<FirstComponent /><SecondComponent />您可以直接作为props访问状态,<SecondComponent />也可以从props中初始化其状态。欲了解更多信息,请阅读

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

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} />
      </>
    );
  }
}

并在<SecondComponent />

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

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

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

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

例子

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>

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

这是您的顶级(父)组件(用于保持状态的基于类的组件),然后通过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 中初始化的数据传递给您<DisplayFirstData />通过 prop 数据调用的第二个组件,对于<DisplaySecondData />

这是您的子组件 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;

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

作为旁注:我不知道为什么你需要 2 个不同的组件,它们基本上做完全相同的事情,但无论如何,上面的例子是这样做的方法......此外,在你的学习之旅中,你应该得到了解并喜欢高阶组件模式上下文 API(我怀疑当您不断尝试构建它时,您将需要它们......)