[[ Patócs Attila / 2020-05-09 ]]
// React //
509
React redux

A redux egy adatokat tároló objektum, amibe helyezhetünk adatokat és olvashatjuk ki őket bármelyik másik komponensben is. Reduxban célszerű tárolni a profil adatokat beállításokat, olyan adatokat amik ritkán változnak, de sokszor van rájuk szükség, így nem kell folyamatosan újra lekérdezni őket.

Tegyük fel a react-redux csomagot az npm-el.

A chrome böngészőben levő redux-os devtool-os plugin-t használhatjuk ha szükséges, hogy megtudd nézni a böngészőben a store/state aktuális tartalmát. Ez a fejlesztésnél nagy segítség lehet. https://chrome.google.com/webstore/detail/redux-devtools/lmhkpmbekcpmknklioeibfkpmmfibljd

A redux használatához szükséges fájlokat négy részre osztjuk. Actions, action-types, reducers, services.

Az action-type-ban definiáljuk a redux-ban használható hívások azonosítóit. Példa action-type-ra:

// CITY
export const GET_CITY = 'GET_CITY'
export const GET_CITY_SUCCESS = 'GET_CITY_SUCCESS'
export const GET_CITY_FAILED = 'GET_CITY_FAILED'
 
export const GET_CITY_LIST = 'GET_CITY_LIST'
export const GET_CITY_LIST_SUCCESS = 'GET_CITY_LIST_SUCCESS'
export const GET_CITY_LIST_FAILED = 'GET_CITY_LIST_FAILED'
 
export const CREATE_CITY = 'CREATE_CITY'
export const EDIT_CITY = 'EDIT_CITY'
export const DELETE_CITY = 'DELETE_CITY'
 
export const DELETE_CITY = 'DELETE_CITY'export const DELETE_CITY = 'DELETE_CITY'export const DELETE_CITY = 'DELETE_CITY'export const DELETE_CITY = 'DELETE_CITY'export const DELETE_CITY = 'DELETE_CITY'export const DELETE_CITY = 'DELETE_CITY'export const DELETE_CITY = 'DELETE_CITY'export const DELETE_CITY = 'DELETE_CITY'

Az action-ökben deklaráljuk azokat a függvényeket, amiket meghívunk majd a komponensekből. A service-eket hívjuk meg bennük és átadjuk a redux-nak a service fügvények értékeit. Egy példa actions-re:

import * as CityService from '../services/city'
import * as actionTypes from 'modules/his/actions/action-types'
 
export const getCityList = (params) => {
  return async (dispatch) => {
    try {
      dispatch({
        type: actionTypes.GET_CITY_LIST,
      })
 
      let citylist = await CityService.getCityList(params)
 
      dispatch({
        type: actionTypes.GET_CITY_LIST_SUCCESS,
        payload: citylist,
      })
 
      return citylist
    } catch (error) {
      console.log(error)
      dispatch({
        type: actionTypes.GET_CITY_LIST_FAILED,
        payload: error,
      })
 
      throw error
    }
  }
}
 
export const getCity = (id) => {
  return async (dispatch) => {
    try {
      dispatch({ type: actionTypes.GET_CITY })
      const city = await CityService.getCity(id)
      dispatch({
        type: actionTypes.GET_CITY_SUCCESS,
        payload: city,
      })
 
      return city
    } catch (error) {
      dispatch({ type: actionTypes.GET_CITY_FAILED })
      throw error
    }
  }
}
 
export const createCity = (cityData) => {
  return async (dispatch, getState) => {
    let city = await CityService.createCity(cityData)
 
    if (city['City'].ID) {
      city = { ...cityData, ID: city['City'].ID }
    }
    dispatch({
      type: actionTypes.CREATE_CITY,
      payload: city,
    })
 
    return city
  }
}
 
export const editCity = (id, cityData) => {
  return async (dispatch, getState) => {
    await CityService.editCity(cityData, id)
 
    dispatch({
      type: actionTypes.EDIT_CITY,
      payload: cityData,
    })
 
    return cityData
  }
}
 
export const deleteCity = (id) => {
  return async (dispatch, getState) => {
    await CityService.deleteCity(id)
 
    dispatch({
      type: actionTypes.DELETE_CITY,
      payload: id,
    })
 
    return id
  }
}

A reducer-ben kezeljük a fent definiált action-öket az action-type-okkal. Bekerülnek a redux state-be az adatok vagy onnan olvassuk ki őket és adjuk vissza az action-öknek. Reducer példa fájl tartalma:

import {
  GET_CITY_LIST,
  GET_CITY,
  GET_CITY_FAILED,
  GET_CITY_LIST_SUCCESS,
  GET_CITY_SUCCESS,
  CREATE_CITY,
  DELETE_CITY,
  EDIT_CITY,
} from 'modules/his/actions/action-types'
 
const INITIAL_STATE = {
  loading: false,
  error: null,
  data: { data: [], count: 0 },
}
 
export default (state = INITIAL_STATE, action) => {
  switch (action.type) {
    case GET_CITY_LIST:
      return {
        ...state,
        loading: true,
      }
    case GET_CITY:
      return {
        ...state,
        loading: true,
      }
    case GET_CITY_SUCCESS:
      return {
        ...state,
        loading: false,
        city: action.payload || {},
      }
    case GET_CITY_LIST_SUCCESS:
      return {
        ...state,
        loading: false,
        data: { data: action.payload.data, count: action.payload.total },
      }
    case GET_CITY_FAILED:
      return {
        ...state,
        loading: false,
        error: action.payload,
      }
    case CREATE_CITY:
      return {
        ...state,
        data: {
          data: [...state.data.data, action.payload],
          count: state.data.count++,
        },
      }
    case EDIT_CITY:
      return {
        ...state,
        data: {
          data: [...state.data.data.filter((city) => city.KOD !== action.payload.KOD), Object.assign({}, action.payload)],
          count: state.data.count,
        },
      }
    case DELETE_CITY:
      return {
        ...state,
        data: {
          data: state.data.data.filter((city) => city.KOD !== action.payload),
          count: state.data.count--,
        },
      }
    default:
      return state
  }
}

Service példa fájl, amit az action hív meg:

import qs from 'query-string'
import request from 'libs/request'
import { Methods } from 'libs/http'
 
const BASE_URL = '/city'
 
export const getCity = async (id) => {
  return await request({
    method: Methods.GET,
    resource: `${BASE_URL}/show/${id}`,
  })
}
 
export const createCity = async (data) => {
  return await request({
    method: Methods.POST,
    resource: `${BASE_URL}/store`,
 
    data,
  })
}
 
export const editCity = async (data, id) => {
  return await request({
    method: Methods.PUT,
    resource: `${BASE_URL}/update/${id}`,
 
    data,
  })
}
 
export const deleteCity = async (id) => {
  return await request({
    method: Methods.DELETE,
    resource: `${BASE_URL}/destroy/${id}`,
  })
}
 
export const getCityList = async (params) => {
  return await request({
    method: Methods.GET,
    resource: `${BASE_URL}?${qs.stringify(params, {
      encode: false,
      arrayFormat: 'bracket',
    })}`,
  })
}

Komponens-ben bekell "connect"-elnünk a használathoz:

import React, { PureComponent } from 'react';
import { connect } from 'react-redux'
import { getCityList, getCity, createCity, editCity, deleteCity } from './action/cityAction'
 
class CityPage extends PureComponent {
  static propTypes = {
    getCityList: PropTypes.func.isRequired,
    getCity: PropTypes.func.isRequired,
    createCity: PropTypes.func.isRequired,
    editCity: PropTypes.func.isRequired,
    deleteCity: PropTypes.func.isRequired,
  };
 
  ...
  load = async (params = this.props.params) => {
       const city = await this.props.getCityList(...params);
  }
}
 
const mapStateToProps = (state) => {
  return {
    city: state.city.data
  }
}
 
const mapDispatchToProps = {
   getCityList,
   getCity,
   createCity,
   editCity,
   deleteCity
}
 
export default connect(
  mapStateToProps,
  mapDispatchToProps
)(Counter)

Fejlesztéshez a redux tartalmát megtekinteni fel lehet tenni egy chrome extension-t, ami sokat segít. https://chrome.google.com/webstore/detail/redux-devtools/lmhkpmbekcpmknklioeibfkpmmfibljd

Olvasnivaló https://react-redux.js.org/ https://react-redux.js.org/introduction/quick-start

on this page
    back to top