使用异步数据初始化组件

IT技术 reactjs redux react-redux redux-thunk
2021-05-15 14:00:55

我正在尝试弄清楚如何以及在何处为 react + redux + thunk 中的选择框加载数据(即在我的操作中调用调度)。我不确定它是否应该放在我的 App 容器的构造函数中,或者我应该将它加载到我的组件中(在我的示例中:“MyDropdown”)

我的主要应用程序:

import MyDropdown from '../components/mydropdown';
// Should i import my action here and then...
// import { loadData } from '../actions';

class App extends Component {
  render() {
    return (
      <div className="page-content">
        <div className="option-bar">
          // SEND it as a PROP inside MyDropdown... 
          <MyDropdown />
        </div>
      </div>
    );
  }
}
export default App;

我的组件

// OR.. Should i load it in my MyDropdown component here?
import { loadData } from '../actions';

class MyDropdown extends Component {
  // If i load it here on load, how do i do it?
  render() {
    return(
      <select>
         {renderOptions()}
      </select>
    );
  }
}

我已经在我的 App 类中尝试了 componentDidMount(),但它似乎没有用。将初始化数据和操作调用放在那里似乎是有意义的,因为它将全部集中,而不是在我的子组件中调用操作。另外,我将有多个选择框需要在启动时加载,所以我的 App 类可能会增长很多,这是正确的方法吗?我不确定最佳实践是什么,因为我才刚刚开始学习react。

1个回答

您应该将数据组件与表示组件分开(请参阅此处的帖子)。

因此,在您的小示例中,MyDropdown应该传递渲染组件所需的所有数据。这意味着在 App(或实际渲染视图的组件的某些父组件)中获取数据。

由于您正在使用 React 和 Redux,因此react-redux库提供了一个辅助函数来生成容器,以获取您的表示组件所需的数据。

为此,请更改App为:

import { connect } from 'react-redux'
import MyDropdown from '../components/mydropdown';
import { loadData } from '../actions';

// This class is not exported
class App extends Component {
  componentDidMount() {
    this.props.loadData()
  }
  render() {
    return (
      <div className="page-content">
        <div className="option-bar">
          <MyDropdown data={this.props.data}/>
        </div>
      </div>
    );
  }
}

function mapStateToProps(state) {
  const { data } = state
  return {
    data
  }
}

function mapDispatchToProps(dispatch) {
  return {
    loadData(){
      dispatch(loadData())
    }
  }
}

// Export a container that wraps App
export default connect(mapStateToProps, mapDispatchToProps)(App);

或者,您可以保持App不变并更改MyDropdown为:

import { connect } from 'react-redux'
import { loadData } from '../actions';

// Exporting this allows using only the presentational component
export class MyDropdown extends Component {
  componentDidMount() {
    this.props.loadData()
  }
  render() {
    return(
      <select>
         {renderOptions(this.props.data)}
      </select>
    );
  }
}

function mapStateToProps(state) {
  const { data } = state
  return {
    data
  }
}

function mapDispatchToProps(dispatch) {
  return {
    loadData(){
      dispatch(loadData())
    }
  }
}

// By default, export the container that wraps the presentational component
export default connect(mapStateToProps, mapDispatchToProps)(MyDropdown);

在这两种情况下,查看最后实际导出为默认值的内容。它不是组件;这是 的回报connect该函数包装您的展示组件并返回一个容器,该容器负责为展示组件获取数据和调用操作。

这为您提供了所需的分离,并允许您灵活地使用演示组件。在任一示例中,如果您已经拥有需要渲染的数据MyDropdown,您可以只使用演示组件并跳过数据获取!

您可以在此处的 Redux 文档中查看完整示例