【问题标题】:How to dispatch an action on page load in react-redux?如何在 react-redux 中调度页面加载操作?
【发布时间】:2016-08-25 03:56:51
【问题描述】:

我必须显示一个包含大量数据的表格。有一个分页按钮,每页显示 10 条记录。我有一个名为“FETCH”的按钮,点击它的表格正在填充。如何在页面加载时加载我的表格。

action.js

import fetch from 'isomorphic-fetch';
export const ADD_BENEFICIARY = 'ADD_BENEFICIARY';
export const REMOVE_BENEFICIARY = 'REMOVE_BENEFICIARY';

export const ADD_PLAN_TO_COMPARE = 'ADD_PLAN_COMPARE';
export const REMOVE_PLAN_FROM_COMPARE = 'REMOVE_PLAN_COMPARE';
export const SHOW_PLAN_COMPARE = 'SHOW_PLAN_COMPARE';

export const NEXT_PAGE_PLAN_LIST = 'NEXT_PAGE_PLAN_LIST';
export const PREV_PAGE_PLAN_LIST = 'PREV_PAGE_PLAN_LIST';
export const REQUEST_PAGE_PLAN_LIST = 'REQUEST_PAGE_PLAN_LIST';
export const RECEIVE_PAGE_PLAN_LIST = 'RECEIVE_PAGE_PLAN_LIST';

export const showNextPageOfPlans = () => {

  return {
    type: NEXT_PAGE_PLAN_LIST
  }
}

export const showPreviousPageOfPlans = () => {

  return {
    type: PREV_PAGE_PLAN_LIST
  }
}

export const requestPageOfPlans = (startIdx, pageSize) => {

  return {
    type: REQUEST_PAGE_PLAN_LIST,
    start: startIdx,
    pageSize: pageSize
  }
}

export const receivePageOfPlans = (startIdx, json) => {

  return {
    type: RECEIVE_PAGE_PLAN_LIST,
    start: startIdx,
    plans: json
  }
}


export const fetchPlans = (startIdx, pageSize) => {

    var str = sessionStorage.getItem('formValue'); //JSON.stringify(formValues);

  return function (dispatch) {
    dispatch(requestPageOfPlans(startIdx, pageSize));
    return fetch('http://172.16.32.57:9090/alternatePlans/plans/list/', {method: 'post', body: str, headers: new Headers({'Content-Type': 'application/json'})  })
      .then(response => response.json())
      .then(json =>
        dispatch(receivePageOfPlans(startIdx, json))
      )
  }
}

reducer.js

import { REQUEST_PAGE_PLAN_LIST, RECEIVE_PAGE_PLAN_LIST,
         NEXT_PAGE_PLAN_LIST, PREV_PAGE_PLAN_LIST } from './actions';

const initialPaging = {

  startIndex: 0,
  lastIndex: 0,
  pageSize: 10
}

const paging = (state = initialCurrentPage, action) => {

  switch (action.type) {

    case NEXT_PAGE_PLAN_LIST:

      if (state.startIndex+state.pageSize <= state.lastIndex) {

        return { ...state, startIndex: state.startIndex+state.pageSize };
      }
      else {

        return state;
      }

    case PREV_PAGE_PLAN_LIST:

      if (state.startIndex-state.pageSize >= 0) {

        return { ...state, startIndex: state.startIndex-state.pageSize };
      }
      else {

        return state;
      }

    case REQUEST_PAGE_PLAN_LIST:

      return { ...state, isFetching: true };

    case RECEIVE_PAGE_PLAN_LIST:

      return { ...state, isFetching: false };

    default:
      return state;
  }

}

var initialPlans = [];

const plans = (state = initialPlans, action) => {

  switch (action.type) {

    case RECEIVE_PAGE_PLAN_LIST:
      return action.plans.plans;

    default:
      return state;
  }
}


const allReducers = (state = {}, action) => {

  let items = plans(state.plans, action);
  return {
    plans: items,
    paging: paging({ ...initialPaging, ...state.paging, lastIndex: items.length-1 }, action)
  }
}

export default allReducers;

附:我是 react-redux 的新手。官方文档很好,但给出的解释很少。

【问题讨论】:

    标签: reactjs react-redux isomorphic-fetch-api


    【解决方案1】:

    您可以从页面的 react 组件的 componentDidMount() 或任何有意义的地方调用它。所以在那个组件文件中:

    import { requestPageOfPlans } from 'actions';
    import React from 'react';
    import { connect } from 'react-redux';
    
    class MyComponent extends React.Component {
      componentDidMount() {
        this.props.requestPageOfPlans();
      }
    }
    
    export default connect((state) => state, { requestPageOfPlans })(MyComponent);
    

    所以这里的关键是连接设置。第一个参数是您希望如何将状态(您的 reducer)转换为 props 的数据。根据需要进行调整。第二个是您希望绑定的操作。您也可以手动导入调度,但我个人喜欢这种模式。它将动作设置为组件上的道具,您可以这样称呼它。只需根据需要将参数传递给它。这个页面在这里:https://github.com/reactjs/react-redux/blob/master/docs/api.md#connectmapstatetoprops-mapdispatchtoprops-mergeprops-options 更详细地解释了连接功能。

    编辑

    鉴于您在前端进行分页,您需要调整连接 mapStateToProps 函数以将分页数据向下传递给组件,然后循环通过它以显示您需要的内容。就我个人而言,我会在后端进行分页,并对每个页面进行新的请求。取决于您期望拥有多少条记录。

    所以在连接中做这样的事情:

    export default connect((state) => {
      return {
        startIndex: state.paging.lastIndex,
        pageSize: state.paging.pageSize,
        lastIndex: state.paging.lastIndex,
        plans: state.plans
      };
    }, { requestPageOfPlans })(MyComponent);
    

    然后在您的组件中,使用这些索引遍历计划:

     render() {
       const plans = [];
       const maxIndex = Math.min(this.props.startIndex + this.props.pageSize, this.props.lastIndex);
       for (let i = this.props.startIndex || 0; i < maxIndex; i++) {
         const plan = this.props.plans[i];
         plans.push(<Plan key={plan.id} plan={plan} />);
       }
    
       return (
         <ul>{plans}</ul>
       );
     }
    

    再次假设您计划如何渲染它,如果您有一个名为 Plan 的组件等。但这大致就是您可以使用它的方式。

    【讨论】:

    • 从 'reducers' 导入 { requestPageOfPlans };我这样做了.. import { requestPageOfPlans } from 'action';它正在获取所有结果,并且由于该分页不起作用。
    • 啊抱歉,是的,我没有仔细看那里的文件名。我知道我会在那里捏造一些进口商品。进行了编辑以进一步解释您可能如何使用这些数据。
    【解决方案2】:

    componentDidMount 是加载第一个页面的好时机。

    顺便说一句,在我看来,页面更改不是动作,它只是加载数据的一些参数。

    动作创作者

    const userurl = '/rest/users'
    
    export const loadUsers = (page = 0) => {
      return (dispatch) => {
        axios.get(userurl+"?page="+page)
        .then(function(resp) {
          dispatch(loadUsersOK(resp.data._embedded.users, resp.data.page));
        })
        .catch(function(error) {
         ...
        })
      };
    }
    

    组件 JSX

    <span style={{marginRight:15, fontSize: 14, color: '#333'}}>{page.number*page.size+1}-{page.number*page.size+page.size} of {' '} {page.totalElements}</span>
    <FlatButton style={flatButtonStyle} icon={<NavigationChevronLeft/>} onTouchTap={this.prevPage} />
    <FlatButton style={flatButtonStyle} icon={<NavigationChevronRight/>} onTouchTap={this.nextPage} />
    

    组件处理程序

     prevPage() {
        const { page } = this.props.users;
        this.props.loadUsers(page.number - 1);
      }
    
      nextPage() {
        const { page } = this.props.users;
        this.props.loadUsers(page.number + 1);
      }
    

    连接

    const mapStateToProps = state => {
      return {
        users: state.users
      }
    }
    
    const mapDispatchToProps = (dispatch, ownProps) => {
      return {
        loadUsers: (page=0) => dispatch(loadUsers(page))
      }
    }
    
    const Wrapped = connect(
      mapStateToProps,
      mapDispatchToProps
    )(Users)
    

    只有一个动作

    export const loadUsersOK = (result, page) => ({
      type: LOAD_USERS_OK,
      result,
      page
    })
    

    希望对你有帮助。

    【讨论】:

    • 忽略加载时调度的部分没关系。
    猜你喜欢
    • 2019-09-02
    • 2018-12-09
    • 2017-11-09
    • 1970-01-01
    • 1970-01-01
    • 2021-10-08
    • 2016-11-28
    • 2018-07-16
    • 2020-08-18
    相关资源
    最近更新 更多