Redux在React中的使用
redux
Redux是一个
数据状态管理插件,当使用React或是vue开发组件化的SPA程序时,组件之间共享信息是一个非常大的问题。例如,用户登陆之后客户端会存储用户信息(ID,头像等),而系统的很多组件都会用到这些信息,当使用这些信息的时候,每次都重新获取一遍,这样会非常的麻烦,因此每个系统都需要一个管理多组件使用的公共信息的功能,这就是redux的作用。
简单使用
import { createStore } from 'redux'
- 第一步:定义计算规则,即reducer
function counter(state = 0, action) {
switch (action.type) {
case 'INCREMENT':
return state + 1
case 'DECREMENT':
return state - 1
default:
return state
}
}
- 第二步:根据计算规则生成store
let store = creatStore(counter);
- 第三步:定义数据(state)变化之后的派发规则
store.subscribe(() => {
console.log('fn1 -> current state', store.getState())
})
store.subscribe(() => {
console.log('fn2 -> current state', store.getState())
})
- 第四步:触发数据变化
store.dispatch({
type: 'INCREMENT',
})
在React中使用
redux经常和react搭配使用,使用React开发系统,绝大部分都需要结合Redux来使用,下面介绍一下如何在React中使用redux.
前四步和之前的差不多,但是要注意结构的拆分。
导入依赖
npm install redux --save
npm install react-redux --save
文件目录结构
-
reducers
-
index.js
Reducer 函数负责生成 State。由于整个应用只有一个 State 对象,包含所有数据,对于大型应用来说,这个 State 必然十分庞大,导致 Reducer 函数也十分庞大。若把传入Reducer的Action改变为State的属性,属性间没有关联,我们就可以把Reducer函数拆分,不同函数负责处理不同属性,最终用
combineReducers合并成一个大的Reducer即可。import { combineReducers } from 'redux'; import userInfo from './userInfo' const rootRuducer = combineReducers({ userInfo, //userInfo是State的一个属性,也是一个action方法,同名。若不想同名,可写成a: doSomethingWithA的形式(a是State的属性)。 }) export default rootRuducer; -
userInfo.js
import * as actionTypes from '../constants/userInfo'; const initState = {} export default function userInfo (state = initState, action) { switch(action.type) { case actionTypes.UPDATE_CITYNAME: return action.data default: return state } }
-
-
actions
-
userInfo.js
import * as actionTypes from '../constants/userInfo'; export function updateCityName(data) { return { type: actionTypes.UPDATE_CITYNAME, data, } } export function XXX(){ return {} }
-
-
constants
-
userInfo.js
被多个地方引用,这样可以方便修改
export const UPDATE_CITYNAME = 'UPDATE_CITYNAME';
-
-
store
-
configureStore.js
导出创建store的函数
import { createStore } from 'redux'; import rootRuducer from '../reducers'; export default function configureStore(initState) { const store = createStore(rootRuducer, initState, window.devToolsExtension ? window.devToolsExtension() : undefined ); return store; }
-
-
containers
存放页面的文件夹
-
index.js
mapStateToProps会订阅 Store,每当state更新的时候,就会自动执行,重新计算 UI 组件的参数,从而触发 UI 组件的重新渲染。mapStateToProps的第一个参数总是state对象,还可以使用第二个参数,代表容器组件的props对象。mapDispatchToProps是connect函数的第二个参数,用来建立 UI 组件的参数到store.dispatch方法的映射。也就是说,它定义了哪些用户的操作应该当作 Action,传给 Store。它可以是一个函数,也可以是一个对象。如果
mapDispatchToProps是一个函数,会得到dispatch和ownProps(容器组件的props对象)两个参数,返回一个对象,该对象的每个键值对都是一个映射,定义了 UI 组件的参数怎样发出 Action。bindActionCreators(actionCreators, dispatch)把一个 value 为不同 action creator 的对象,转成拥有同名 key 的对象。同时使用dispatch对每个 action creator 进行包装,以便可以直接调用它们。一般情况下你可以直接在
Store实例上调用dispatch。如果你在 React 中使用 Redux,react-redux 会提供dispatch函数让你直接调用它 。惟一会使用到
bindActionCreators的场景是当你需要把 action creator 往下传到一个组件上,却不想让这个组件觉察到 Redux 的存在,而且不希望把dispatch或 Redux store 传给它。import React from 'react'; import { bindActionCreators } from 'redux'; import { connect } from 'react-redux'; import * as userInfoActionsFromOtherFile from '../actions/userInfo.js'; class App extends React.Component { constructor(props) { super(props); this.state = { initDone: false } } componentDidMount() { this.setState({ initDone: true, }) } render() { return ( <div> {this.state.initDone ? this.props.children : 'loadding...'} </div> ) } } function mapStateToProps(state) { return { userInfo: state.userinfo, } } function mapDispatchToProps(dispatch) { return { userInfoAction: bindActionCreators(userInfoActionsFromOtherFile, dispatch), } } export default connect( mapStateToProps, mapDispatchToProps // 定义了哪些用户的操作应该当作 Action,传给 Store )(App);
-
-
index.js
React-Redux 提供
Provider组件,可以让容器组件拿到state。所以在入口文件夹中,先创建store,然后再把包裹一层。 import React from 'react'; import ReactDOM from 'react-dom'; // import { render } from 'react-dom'; import { Provider } from 'react-redux'; import configureStore from './store/configureStore'; import App from './containers//index'; const store = configureStore(); ReactDOM.render( <Provider store={store}> <App /> </Provider>, document.getElementById('root') );

浙公网安备 33010602011771号