Use Redux
一、Redux
简介
Redux
是JavaScript
状态管理容器。
React
跟Redux
没有什么直接的联系。就像java
和JavaScript
之间。因为redux
在react
中使用起来比较好用,所以常选取redux
作为react
的状态管理容器。
-
优点:
- 可以集中管理数据,多组件共享数据。
- 唯一的数据源,只能通过纯函数来修改。
-
缺点:
- 实现原理是 发布订阅模式,
dispatch
会触发给纯函数中type
相同的操作,细粒度不够。 - 需要手动监听,并且组件销毁取消监听。写起来比较麻烦。
- 实现原理是 发布订阅模式,
-
Redux
的使用流程[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eUF6NYzs-1630293783190)(/Users/yesshuai/Library/Application Support/typora-user-images/image-20210308162611618.png)]
二、Redux
的三大原则
-
单一数据源
整个应用的
state
被储存在一棵object tree
中,并且这个object tree
只存在于唯一一个store
中。 -
state
是只读的唯一改变
state
的方法就是触发action
,action
是一个用于描述已发生事件的普通对象。 -
使用纯函数来执行修改
为了描述
action
如何改变state tree
,你需要编写reducer
。
三、Redux
使用步骤
-
安装
Redux
$ npm i redux --save
-
创建
store
这个文件主要是为了抛出创建好的
store
实例import { createStore } from 'redux' import reducer from './reducer' const store =createStore(reducer) export default store
-
创建
reducer
纯函数reducer
纯函数,接收defaultState
和action
并返回一份全新的state
。 最后暴露这个函数,给到创建store
时 使用const defaultState ={} export default (state=defaultState, action)=> { if (action.type === 'ADD_SHOP') { let newState = JSON.parse(JSON.stringify(state)) // 这里要对数据做深拷贝 ///这里做添加操作 return newState } return state }
-
在组件中使用
1. //引入store import store from ’......‘ 2. //通过store身上的getState()方法获取store中的状态 this.state = { name: store.getState().name } 3. //通过store身上的dispatch 方法获取,出发action,改变redux中的状体 store.dispatch({ type:'ADD_SHOP', //type是必传参数 value: xxx //是要传入的值 }) 4. //在组件创建时候监听改变 unsubscribe = store.subscribe(() => { this.setState(store.getState()) }) 5. //在组件销毁时候取消监听 this.unsubscribe()
四、react-redux
Redux
是状态管理容器,react-redux
是一款redux
的插件,react-redux
依赖redux
,所以使用react-redux
要先下载redux
包。如果说做个比喻的话,
redux
是一款手动挡车型,那么react-redux
则是一款自动档车型。
react-redux
帮助开发者完成了状态的订阅和取消订阅的步骤。
-
安装
react-redux
$ npm i react-redux --save
-
使用
1. //在入口文件引入store import store from ’......‘ 2. //在入口文件引入 Provider 组件,包裹在项目根组件的zuiwaiceng ReactDOM.render( <Provider store={store}> <BrowserRouter> <App /> </BrowserRouter> </Provider> , document.getElementById('root') ) 3. //在需要用到状态的组件 引入高阶组件包裹住组件 import { connect } from 'react-redux' export default connect(参数一,参数二)(组件) //参数一: mapStateToProps = (state) => { return { name: state.name } } //参数二: mapDispatchToProps = (dispatch) => { return { changeHomeEnglish: (paylod) => { dispatch({ type: "ADD_SHOP" paload }) } } }
五、拆分 reducer
当项目越做越大的时候,如果所有的状态都保存在一个reducer里就会特别庞大复杂。所以一般做项目都会把reducer 拆分成小模块的reducer。
- 总得
reducer
import { combineReducers } from 'redux'
import langreducer from './reducers/langreducer'
export default combineReducers({
language: langreducer
})
langreducer
import { combineReducers } from 'redux'
import login from './reducers/loginlangreducer'
import home from './reducers/homelangreducer'
import topup from './reducers/topuplangreducer'
export default combineReducers({
login,
home,
topup
})
homelangreducer
import home from '../../../../../lang/zh_CN/home'
import * as actionTypes from '../../../../actions/language/actiontypes'
const defaultState = {
...home
}
export default (state = defaultState, action) => {
if (action.type === actionTypes.CHANGE_HOME_ENGLISH) {
let newState = JSON.parse(JSON.stringify(state))
newState = action.payload
return newState
}
return state
}
六、redux
异步
Redux 的操作流程是同步的代码,如果需要有异步的程序,那么就需要使用到中间件。
异步中间件:
redux-thunk
redux-saga
redux-promise
-
redux-thunk
使用redux-thunk 中间件,相当于对store.dispatch 进行了重写
const next = store.dispatch store.dispatch = function (action) { if (typeof action === 'function') { action(next, store.getState) } else { store.dispatch(action) } }