web-dev-qa-db-ja.com

react-reduxでページのロード時にアクションをディスパッチする方法は?

大量のデータを含むテーブルを表示する必要があります。ページごとに10レコードを表示するページネーションボタンがあります。 「FETCH」というボタンが1つあり、それをクリックするとテーブルが表示されます。ページのロード時にテーブルをロードする方法。

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は初めてです。公式文書は良いですが、説明はほとんどありません。

12
Raj Rj

ページの反応コンポーネントの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);

ここで重要なのは、接続のセットアップです。最初のパラメーターは、状態(リデューサー)を小道具用のデータに変換する方法です。必要に応じて調整してください。 2番目は、どのアクションをバインドするかです。ディスパッチを手動でインポートすることもできますが、個人的にはこのパターンが好きです。コンポーネントのアクションとしてアクションを設定し、そのように呼び出すことができます。必要に応じて引数を渡すだけです。こちらのページ: https://github.com/reactjs/react-redux/blob/master/docs/api.md#connectmapstatetoprops-mapdispatchtoprops-mergeprops-options は接続について説明していますより詳細に機能します。

編集

フロントエンドでページネーションを行う場合、connect 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などのコンポーネントがある場合、レンダリングの計画方法について再びいくつかの仮定を立てます。しかし、それはおおよそそれをどのように扱うことができるかです。

11
agmcleod

componentDidMountは、最初のページを読み込むのに適したタイミングです。

ところで、私の意見では、ページの変更はアクションではなく、データをロードするための単なるパラメーターです。

ActionCreator

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)

1つのアクションのみ

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

助けてください。

3
nonocast