Dalam posting ini kita akan menyentuh tindakan menulis dan reducer. Untuk memulainya, pertimbangkan 'aliran' yang khas, di mana kami melakukan operasi berikut (lebih lanjut, kami mengerjakan ulang semuanya sehingga kode kami memenuhi prinsip SOLID).
1. buat file dengan konstanta (di sini kita simpan nama-nama jenis tindakan)
export const REQUEST_DATA_PENDING = "REQUEST_DATA_PENDING"; export const REQUEST_DATA_SUCCESS = "REQUEST_DATA_SUCCESS"; export const REQUEST_DATA_FAILED = "REQUEST_DATA_FAILED"; export const PROFILES_PER_PAGE = "PROFILES_PER_PAGE"; export const CURRENT_PAGE = "CURRENT_PAGE";
2. buat file tempat kami menggambarkan tindakan (di sini kami membuat permintaan untuk akun pengguna, dan pagination). Juga dalam contoh redux-thunk digunakan (lebih lanjut kami akan menolak dependensi yang sama):
export const requestBigDataAction = () => (dispatch) => { fetchingData(dispatch, BIG_DATA_URL, 50); } export const changeCurrentPAGE = (page) => ({ type: CURRENT_PAGE, payload: page }) function fetchingData(dispatch, url, profilesPerPage) { dispatch({type: REQUEST_DATA_PENDING}); fetch(url) .then((res) => { if(res.status !== 200) { throw new Error (res.status); } else { return res.json(); } }) .then((data) => {dispatch({type: REQUEST_DATA_SUCCESS, payload: data})}) .then(() => dispatch({type: PROFILES_PER_PAGE, payload: profilesPerPage})) .catch((err) => dispatch({type: REQUEST_DATA_FAILED, payload: ` . ${err.message}`})); }
3. kami menulis peredam
import { REQUEST_DATA_PENDING, REQUEST_DATA_SUCCESS, REQUEST_DATA_FAILED, PROFILES_PER_PAGE, CURRENT_PAGE } from '../constants/constants'; const initialState = { isPending: false, buffer: [], data: [], error: "", page: 0, profilesPerPage: 0, detailedProfile: {} } export const MainReducer = (state = initialState, action = {}) => { switch(action.type) { case REQUEST_DATA_PENDING: return Object.assign({}, state, {isPending: true}); case REQUEST_DATA_SUCCESS: return Object.assign({}, state, {page : 0, isPending: false, data: action.payload, error: "", detailedProfile: {}, buffer: action.payload}); case REQUEST_DATA_FAILED: return Object.assign({}, initialState, {error: action.payload}); case PROFILES_PER_PAGE: return Object.assign({}, state, {profilesPerPage: action.payload}); case CURRENT_PAGE: return Object.assign({}, state, {page: action.payload}); default: return state; } }
4. konfigurasikan toko (gunakan middleware thunkMiddleware)
import React from 'react'; import ReactDOM from 'react-dom'; import './index.css'; import App from './App'; import {createStore, applyMiddleware} from 'redux'; import {Provider} from 'react-redux'; import thunkMiddleware from 'redux-thunk'; import {MainReducer} from './reducers/mainReducer'; const store = createStore(MainReducer, applyMiddleware(thunkMiddleware)); ReactDOM.render( <Provider store={store}> <App /> </Provider>, document.getElementById('root'));
5. sambungkan komponen ke redux
const mapDispatchToProps = (dispatch)=>{ return { onRequestBigData: (event) =>{ dispatch(requestBigDataAction()); } } };
sambungkan tombol pagination ke redux
const mapDispatchToProps = (dispatch)=>{ return { onChangePage: (page) =>{ dispatch(changeCurrentPAGE(page)); } } };
Masalah: peredam kami adalah salah satu pernyataan peralihan besar, oleh karena itu, ketika menambahkan tindakan baru, atau mengubah perilakunya, kita perlu mengubah peredam kami, yang melanggar prinsip SOlid (prinsip tanggung jawab tunggal dan prinsip keterbukaan / kedekatan).
Solusi: polimorfisme akan membantu kita. Tambahkan ke setiap tindakan metode eksekusi, yang akan menerapkan pembaruan dan mengembalikan status yang diperbarui. Kemudian peredam kami akan mengambil formulir
export const MainReducer = (state = initialState, action) => { if(typeof action.execute === 'function') return action.execute(state); return state; };
sekarang ketika menambahkan tindakan baru, kami tidak perlu mengubah peredam, dan itu tidak berubah menjadi monster besar.
Selanjutnya, menyerah redux-thunk dan tulis ulang tindakannya
import React from 'react'; import ReactDOM from 'react-dom'; import './index.css'; import App from './App'; import {createStore} from 'redux'; import {Provider} from 'react-redux';
pergi ke komponen yang terhubung, yang tindakannya tidak sinkron (harus sedikit diperbaiki)
const mapDispatchToProps = (dispatch)=>{ return { onRequestBigData: (event) =>{ requestBigDataAction(dispatch); }, } };
dan lanjutkan ke tindakan itu sendiri dan tambahkan metode eksekusi ke dalamnya
const type = 'bla-bla'; const requestDataPending = {execute: state => ({...state, isPending: true}), type}; const requestDataSuccess = payload => ({ execute: function (state) { return ({...state, page : 0, isPending: false, data: payload, error: "", detailedProfile: {}, buffer: payload}) }, type}) const profilesPerPageAction = profilesPerPage => ({ execute: state => ({...state, profilesPerPage: profilesPerPage}), type }); const requestDataFailed = errMsg => state => ({...state, error: ` . ${errMsg}`}); function fetchingData(dispatch, url, profilesPerPage) { dispatch(requestDataPending); fetch(url) .then((res) => { if(res.status !== 200) { throw new Error (res.status); } else { return res.json(); } }) .then((data) => {dispatch(requestDataSuccess(data))}) .then(() => dispatch(profilesPerPageAction(profilesPerPage))) .catch((err) => dispatch(requestDataFailed(err.message))); } export const requestBigDataAction = (dispatch) => { fetchingData(dispatch, BIG_DATA_URL, 50); } export const changeCurrentPAGE = page => ({ type, execute: state => ({...state, page}) })
Catatan: properti tipe diperlukan (jika Anda tidak menambahkannya, pengecualian akan dilempar). Tetapi bagi kami itu tidak masalah sama sekali. Itu sebabnya kami tidak lagi memerlukan file terpisah yang mencantumkan jenis tindakan.
PS: Dalam artikel ini, kami menerapkan prinsip-prinsip SRP dan OCP, polimorfisme, meninggalkan perpustakaan pihak ketiga dan membuat kode kami lebih bersih dan dapat dipertahankan.