web-dev-qa-db-fra.com

Comment envoyer une action au chargement de la page dans react-redux?

Je dois afficher un tableau avec beaucoup de données. Il y a un bouton de pagination qui affiche 10 enregistrements par page. J'ai un bouton appelé "FETCH" lorsque la table est en train de se remplir. Comment charger ma table au chargement de la page.

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;

P.S. Je suis nouveau sur react-redux. La documentation officielle est bonne mais très peu d'explications sont fournies.

12
Raj Rj

Vous l'appelez depuis la componentDidMount() du composant react pour votre page, ou partout où cela a du sens. Donc, dans ce fichier de composant:

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

La clé ici est donc la configuration de la connexion. Le premier paramètre est de savoir comment vous souhaitez transformer l'état (vos réducteurs) en données pour les accessoires. Ajustez cela selon vos besoins. La seconde est quelles actions vous souhaitez lier. Vous pouvez également importer la répartition manuellement, mais j'aime personnellement ce modèle. Il configure les actions comme accessoires sur le composant, et vous pouvez l'appeler de cette façon. Passez-lui les arguments selon vos besoins. Cette page ici: https://github.com/reactjs/react-redux/blob/master/docs/api.md#connectmapstatetoprops-mapdispatchtoprops-mergeprops-options explique la fonction de connexion plus en détail.

Modifier

Étant donné que vous paginez sur le front-end, vous devrez ajuster la fonction connect mapStateToProps pour transmettre les données de pagination au composant, puis les parcourir pour afficher ce dont vous avez besoin. Personnellement, je ferais la pagination à l'arrière, et ferais juste de nouvelles demandes pour chaque page. Cela dépend du nombre d'enregistrements que vous prévoyez d'avoir.

Donc, dans la connexion, faites quelque chose comme ceci:

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

Ensuite, dans votre composant, parcourez les plans en utilisant ces index:

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

Faire à nouveau quelques hypothèses sur la façon dont vous prévoyez de le rendre, si vous avez un composant appelé Plan, etc. Mais c'est à peu près comment vous pouvez travailler avec lui.

11
agmcleod

componentDidMount est un bon moment pour charger votre première page.

BTW, à mon avis, le changement de page n'est pas l'action, c'est juste un paramètre pour charger vos données.

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) {
     ...
    })
  };
}

Composant 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} />

Gestionnaires de composants

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

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

Relier

const mapStateToProps = state => {
  return {
    users: state.users
  }
}

const mapDispatchToProps = (dispatch, ownProps) => {
  return {
    loadUsers: (page=0) => dispatch(loadUsers(page))
  }
}

const Wrapped = connect(
  mapStateToProps,
  mapDispatchToProps
)(Users)

UNE SEULE ACTION

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

Que cela aide.

3
nonocast