redux特点
- Redux 是 JavaScript 状态容器,提供可预测化的状态管理。
- 应用中所有的 state 都以一个对象树的形式储存在一个单一的 store 中。 惟一改变 state 的办法是触发 action,一个描述发生什么的对象。 为了描述 action 如何改变 state 树,你需要编写 reducers。
- 但是模版代码太多,每次改一点业务动辄就需要改四五个文件,着实令人心累。
示例代码
- pageA/store/actions.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| import axios from 'axios'
export const INCREMENT = 'INCREMENT' export const DECREMENT = 'DECREMENT' export const CHANGE = 'CHANGE' export const GET_OPTIONS = 'GET_OPTIONS'
export const increase = () => { return { type: INCREMENT } } export const decrease = () => { return { type: DECREMENT } } export const change = value => { return { type: CHANGE, payload: value } } export const getOptions = () => dispatch => { axios.get('/api/pageA/options') .then(res => { dispatch({ type: GET_OPTIONS, payload: res.data.data }) }) }
|
- pageA/store/reducer.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| import * as actions from './actions'
const initState = { count: 0, optionList: [], }
export default function counter(state = initState, action) { switch (action.type) { case actions.INCREMENT: return { ...state, count: state.count + 1 }; case actions.DECREMENT: return { ...state, count: state.count - 1 }; case actions.CHANGE: return { ...state, count: state.count + Number(action.payload) }; case actions.GET_OPTIONS: return { ...state, optionList: action.payload }; default: return state; } }
|
- pageA/container/main.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| import { connect } from 'react-redux' import { increase, decrease, change, getOptions } from '../store/actions' import view from '../component/main'
const mapStateToProps = store => { const pageAStore = store.pageA
return { count: pageAStore.count, optionList: pageAStore.optionList, } }
const mapDispatchToProps = { increase, decrease, change, getOptions }
export default connect(mapStateToProps, mapDispatchToProps)(view)
|
- pageA/component/main.jsx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| import React, { useState, useEffect } from 'react';
import './main.css';
function PageA({ count, optionList, increase, decrease, change, getOptions, }) {
const [inputValue, setInputValue] = useState('')
const handleInputChange = event => { setInputValue(event.target.value) }
useEffect(() => { getOptions() }, [getOptions])
return ( <div className="page-a"> page a
<br /> <br />
<h2>count: {count}</h2> <button onClick={increase}>increase</button> <button onClick={decrease}>decrease</button>
<br /> <br />
<input value={inputValue} onChange={handleInputChange} type="text" /> <button onClick={() => change(inputValue)}>change</button>
<br /> <br />
<select name="select" id="select"> { optionList.map(item => ( <option key={item} value={item}>{item}</option> )) } </select> </div> ); }
export default PageA;
|
注意点
- redux可以用 redux-thunk 处理请求接口这样的副作用
- redux可以用 combineReducers 整合reducer子模块
1 2 3 4 5 6 7 8 9 10 11 12 13
| import { combineReducers, createStore, applyMiddleware } from 'redux'; import thunk from 'redux-thunk';
import pageA from './pageA/store/reducer'
const rootReducer = combineReducers({ pageA, })
const store = createStore(rootReducer, applyMiddleware(thunk));
export default store
|
拓展:create-react-app 添加 proxy 接口代理
- npm安装 http-proxy-middleware 模块
- scr目录下添加 setupProxy.js 文件
1 2 3 4 5 6 7
| const proxy = require('http-proxy-middleware');
module.exports = function (app) { app.use(proxy.createProxyMiddleware('/api', { target: 'http://127.0.0.1:8000/', })); };
|