redux使用详解
Posted 一杯清泉
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了redux使用详解相关的知识,希望对你有一定的参考价值。
一个状态管理的JS库,用于数据的共享。结构如下:
安装:
yarn add redux
一、简化版的redux
1、src/reducer/store.js
//引入createStore
import createStore from 'redux'
//引入服务的reducer
import reducer from "./reducer";
export default createStore(reducer)
2、src/reducer/reducer.js
const defaultState =
count: 0
const reducer = (preState = defaultState, action) =>
const type, data = action
switch (type)
case 'add':
return
count: preState.count + data
case 'reduce':
return
count: preState.count - data
default:
return defaultState
export default reducer
3、src/reducer/App.js
import React, Component from 'react';
import Button from 'antd'
import 'antd/dist/antd.css'
//用于获取状态
import store from "./reducer/store";
export default class App extends Component
componentDidMount()
//reducer不会触发页面变化,需要state来触发
store.subscribe(() =>
this.setState(store.getState())
)
render()
//获取reducer数据
const count = store.getState()
return (
<div>
<Button type='primary' onClick=this.reduce>-</Button>
<span>count</span>
<Button type='primary' onClick=this.add>+</Button>
</div>
);
reduce = () =>
//通知reducer页面数据变化了
store.dispatch(
type: 'reduce',
data: 1
)
add = () =>
//通知reducer页面数据变化了
store.dispatch(
type: 'add',
data: 1
)
二、完整版的redux
1、为了防止type被多个js引用,不小心写错,引发报错,需要将type设置为常量,创建src/reducer/typeCreators.js文件:
export const ADD = 'add_type'
export const REDUCE = 'reduce_type'
2、创建src/reducer/actionCreators.js文件。统一抽取action:
import ADD, REDUCE from "./typeCreators";
export const addAction = (data) => (
type: ADD,
data
)
export const reduceAction = (data) => (
type: REDUCE,
data
)
三、redux 的异步action
如果action是一个对象,则是同步action;如果action是一个function,这是一个异步action,直接使用action返回函数redux不允许,直接报错,redux认识返回一个对象的action,如下方式是不被允许的:
import store from "./store";
/**
* 异步加的action:返回的是函数,直接使用这种方式会报错
*/
export const addActionAsync = (data, time) =>
return ()=>
setTimeout(()=>
store.dispatch(addAction(data))
,time)
这是需要使用一个中间件来实现异步的的功能,即:redux-thunk。
四、redux-thunk实现异步action
yarn add redux-thunk
1、src/reducer/store.js
import createStore,applyMiddleware from 'redux'
import thunk from "redux-thunk";
import reducer from "./reducer";
/**
* 该文件用于暴露一个store对象
*/
export default createStore(reducer, applyMiddleware(thunk))
这时候直接运行addActionAsync就不会报错了。
addActionAsync本身执行在store中,返回值默认有一个参数dispatch,不需要额外的引入,可以简化为
/**
* 简化版
*/
export const addActionAsync = (data, time) =>
return (dispatch) =>
setTimeout(() =>
//异步任务一般在函数内都会调用同步action
dispatch(addAction(data))
, time)
异步action不是一个必须的需求,异步任务可放在action中执行,也可以放在组件中执行。
五、react-redux
yarn add react-redux
redux是非官方的,使用其他也没啥问题,由于比较好用,官方又集成了redux,推出react-redux,用法更为灵活。如下模型图:
六、react-redux基本使用
- UI组件:一般放在components文件夹下
- 容器组件:一般放在container文件夹下
1、src/components/count/index.jsx:
export default class CountUI extends Component
render()
console.log('UI组件接收到的props:', this.props)
return (
<div>
<Button type='primary' onClick=this.reduce>-</Button>
<span>this.props.count</span>
<Button type='primary' onClick=this.add>同步+1</Button>
<Button type='primary' onClick=this.addAsync>异步+2</Button>
</div>
);
reduce = () =>
this.props.reduce(10)
add = () =>
this.props.add(5)
addAsync = () =>
this.props.addActionAsync(2, 500)
2、src/containers/count/index.jsx:
//引入UI组件
import CountUI from "../../components/count";
//引入connect用于连接UI组件和redux
import connect from "react-redux";
//引入action
import
addAction,
reduceAction,
addActionAsync
from "../../reducer/actionCreators";
//----->状态
function mapStateToProps(state)
return
count: state.count
//----->操作状态的方法
function mapDispatchToProps(dispatch)
return
add: number => dispatch(addAction(number)),
reduce: number => dispatch(reduceAction(number)),
addActionAsync: (number, time) => dispatch(addActionAsync(number, time))
//使用connect创建并暴露一个count的容器组件
export default connect(mapStateToProps, mapDispatchToProps)(CountUI)
- mapStateToProps
1、mapStateToProps函数返回一个对象
2、返回的key作为传递给UI组件的props的key,value作为UI组件props的value
3、mapStateToProps用于传递状态
- mapDispatchToProps
mapDispatchToProps函数返回一个对象
返回的key作为传递给UI组件的props的key,value作为UI组件props的value
mapDispatchToProps用于传递状态的方法
七、react-redux优化使用
1、mapDispatchToProps简写
const mapStateToProps = state => (count: state.count)
//mapDispatchToProps一般写法
const mapDispatchToProps = dispatch => (
add: number => dispatch(addAction(number)),
reduce: number => dispatch(reduceAction(number)),
addActionAsync: (number, time) => dispatch(addActionAsync(number, time))
);
//mapDispatchToProps精简写法,react-redux可以自动调用dispatch完成分发
const mapDispatchToProps =
add: addAction,
reduce: reduceAction,
addActionAsync: addActionAsync
;
//参数1:映射状态
//参数2:映射状态的操作方法
export default connect(mapStateToProps, mapDispatchToProps)(CountUI)
即:mapDispatchToProps既可以当做函数,也可以当做对象。
2、无需自己给组件设置store,只需要给外壳设置
import store from "./reducer/store";
import Provider from "react-redux";
ReactDOM.render(
<Provider store=store>
<App/>
</Provider>,
document.getElementById('root')
);
3、容器组件和UI组件合而为一,将connect写在UI组件的外面
src/containers/count/index.jsx:
import React, Component from 'react';
import connect from "react-redux";
import Button from 'antd'
import 'antd/dist/antd.css'
import
addAction,
reduceAction,
addActionAsync
from "../../reducer/actionCreators";
class Count extends Component
render()
return (
<div>
<Button type='primary' onClick=this.reduce>-</Button>
<span>this.props.count</span>
<Button type='primary' onClick=this.add>同步+1</Button>
<Button type='primary' onClick=this.addAsync>异步+2</Button>
</div>
);
reduce = () =>
this.props.reduce(10)
add = () =>
this.props.add(5)
addAsync = () =>
this.props.addActionAsync(2, 500)
const mapStateToProps = state => (count: state.count)
const mapDispatchToProps =
add: addAction,
reduce: reduceAction,
addActionAsync: addActionAsync
;
export default connect(mapStateToProps, mapDispatchToProps)(Count)
4、使用react-redux之后不需要自己使用store.subscribe检查redux中状态改变了,容器组件自动完成。
八、combineReducers
当有多个reducer时候,需要将reducer合并成一个,否则createStore只接受一个reducer,其他的reducer就没有引入,这时候用到combineReducers:
import createStore, applyMiddleware, combineReducers from 'redux'
import thunk from "redux-thunk";
import countReducer from "./count/reducer";
import personReducer from "./person/reducer";
//所有的reducer保存为一个reducer
const allReducer = combineReducers(
c: countReducer, //count可以根据需求任意命名,比如:c,haha,shu等等
p: personReducer
)
export default createStore(allReducer, applyMiddleware(thunk))
在容器组件中使用的时候:
const mapStateToProps = state =>
//注意这块有个c,需要和combineReducers中的对应
return count: state.c.count
还可以简化,引入reducer.js:
import countReducer from "../reducers/count";
import personReducer from "../reducers/person";
import combineReducers from "redux";
//所有的reducer保存为一个reducer
export default combineReducers(
c: countReducer, //count可以根据需求任意命名,比如:c,haha,shu等等
p: personReducer
)
在store.js中:
import createStore, applyMiddleware from 'redux'
import thunk from "redux-thunk";
import composeWithDevTools from 'redux-devtools-extension';
import allReducer from "./reducers";
export default createStore(allReducer, composeWithDevTools(applyMiddleware(thunk)))
九、react-redux项目结构分类
有时候containers也可以为components包,没有强制要求。
redux其他使用案例参考:
react-redux实现todolist功能_一杯清泉的博客-CSDN博客
以上是关于redux使用详解的主要内容,如果未能解决你的问题,请参考以下文章