在react + redux中预加载组件数据的正确方法

时间:2016-09-06 19:32:09

标签: reactjs redux redux-thunk

我不知道从API预加载数据以供组件使用的正确方法。

我编写了一个无状态组件,它应该呈现数据:

import React, { PropTypes } from 'react';

const DepartmentsList = ({ departments }) => {
  const listItems = departments.map((department) => (
    <li><a href="./{department}">{department.title}</a></li>
  ));
  return (
    <ul>
      {listItems}
    </ul>
  );
};

DepartmentsList.propTypes = {
  departments: PropTypes.array.isRequired
};

export default DepartmentsList;

我有一个动作可以从API中检索数据:

import { getDepartments } from '../api/timetable';

export const REQUEST_DEPARTMENTS = 'REQUEST_DEPARTMENTS';
export const RECEIVE_DEPARTMENTS = 'RECEIVE_DEPARTMENTS';

const requestDepartments = () => ({ type: REQUEST_DEPARTMENTS });
const receiveDepartments = (departments) => ({ type: RECEIVE_DEPARTMENTS, departments });

export function fetchDepartments() {
  return dispatch => {
    dispatch(requestDepartments);
    getDepartments()
      .then(departments => dispatch(
        receiveDepartments(departments)
      ))
      .catch(console.log);
  };
}

现在我想我有几个选项来预加载列表所需的部门。我可以使用redux-thunkmapDispatchToProps将fetchDepartments注入无状态组件并实现componentWillMount或类似的生命周期方法来加载数据 - 但我不需要通过列表通过道具,因为组件总是为自己加载数据,我不想要这样,因为每当创建一个新组件时,数据都是从api而不是商店中提取的......

我看到的另一个建议是使用react-router中的getComponent函数,并在返回组件之前检索所有数据,但是,我不确定它是否是正确的redux方式因为我没有看到如何在那里使用redux-thunk,并且当它只是一个组件所需的数据时,逻辑类似于文件中的所有内容。

这为我提供了在容器组件的生命周期方法中加载数据的唯一看似正常的选项,但我想知道什么是我想要做的最佳实践。

1 个答案:

答案 0 :(得分:12)

最像&reduct-like&#39;处理数据预加载的方法是在包装应用程序的高阶组件的生命周期方法(可能是componentWillMount)中触发异步操作。但是,您不会直接在该组件中使用API​​调用的结果 - 需要使用将其放入应用商店的reducer进行处理。这将要求您使用某种thunk中间件来处理异步操作。然后,您将使用mapStateToProps将其简单地传递给呈现数据的组件。

高阶组件:

const mapStateToProps = (state) => {
  return {
    departments: state.departments
  };
}

const mapDispatchToProps = (dispatch) => {
  return bindActionCreators({
    getDepartments: actionCreators.fetchDepartments
  });
}

class App extends Component {
  componentWillMount() {
    this.props.getDepartments();
  }

  render() {
    return <DepartmentsList departments={this.props.departments} />
  }
}

 export default connect(mapStateToProps, mapDispatchToProps)(App);

减速器:

export function departments(state = [], action) {
  switch(action.type) {
    case 'RECEIVE_DEPARTMENTS':
      return action.departments;
  }
}