Redux
Redux 是 JavaScript 状态容器,提供可预测化的状态管理
三大原则
1. 单一数据源
整个应用的
state
被储存在一棵object tree
中,并且这个object tree
只存在于唯一一个store
中。
console.log(store.getState())
2. State 是只读的
唯一改变
state
的方法就是触发action
,action
是一个用于描述已发生事件的普通对象。
确保了视图和网络请求都不能直接修改 state,相反它们只能表达想要修改的意图。因为所有的修改都被集中化处理,且严格按照一个接一个的顺序执行,因此不用担心 race condition
的出现。 Action 就是普通对象而已,因此它们可以被日志打印、序列化、储存、后期调试或测试时回放出来。
store.dispatch({
type: 'COMPLETE_TODO',
index: 1
})
store.dispatch({
type: 'SET_VISIBILITY_FILTER',
filter: 'SHOW_COMPLETED'
})
3. 使用纯函数来执行修改
为了描述
action
如何改变state tree
,你需要编写reducers
。
Reducer
只是一些纯函数,它接收先前的 state 和 action,并返回新的 state。刚开始你可以只有一个 reducer,随着应用变大,你可以把它拆成多个小的 reducers,分别独立地操作 state tree 的不同部分,因为 reducer 只是函数,你可以控制它们被调用的顺序,传入附加数据,甚至编写可复用的 reducer 来处理一些通用任务
所需依赖包
// src/store/index.js
npm i redux --save
npm i react-redux --save
npm i redux-thunk --save // 一个异步的中间件实现库
npm i redux-persist --save // Redux的持久化的实现(根据实际情况决定是否安装)
Example
// src/store/state/type.js
export const INCREASE = 'INCREASE';
export const DECREASE = 'DECREASE';
export const RESET = 'RESET';
// src/store/state/action.js
import { INCREASE, DECREASE, RESET } from './type';
const increase = () => ({ type: INCREASE });
const decrease = () => ({ type: DECREASE });
const reset = () => ({ type: RESET });
export {
increase,
decrease,
reset
}
// src/store/state/reducer.js
import { combineReducers } from 'redux';
import { INCREASE, DECREASE, RESET} from './type';
// 原始默认state
const defaultState = {
count: 5
}
function counter(state = defaultState, action) {
switch (action.type) {
case INCREASE:
return { ...state, count: state.count + 2 };
case DECREASE:
return { ...state, count: state.count - 2 };
case RESET:
return { ...state, count: 0 };
default:
return state;
}
}
export default combineReducers({
counter
});
// src/store/index.js
import { createStore } from 'redux';
import rootReducer from './state/reducer';
const configureStore = preloadedState => {
return createStore (
rootReducer,
preloadedState
);
}
const store = configureStore();
export default store;
// App.js
import React, { Component } from 'react';
import { Provider } from 'react-redux';
import store from './src/store';
import Login from './src/view';
export default class App extends Component {
render() {
return (
<Provider store={store}>
<Login/>
</Provider>
);
}
}
// Login.js
import React, { useState, Component } from "react";
import { Button, Text, StyleSheet, View } from "react-native";
import { connect } from 'react-redux';
import { increase, decrease, reset } from '@/store/state/action';
class Login extends Component {
constructor(props) {
super(props)
this.state = {
value: 0.6
}
}
_onPressReset() {
this.props.dispatch(reset());
}
_onPressInc() {
this.props.dispatch(increase());
}
_onPressDec() {
this.props.dispatch(decrease());
}
render() {
return (
<View>
<Text style={{color: "red", textAlign: "center", fontSize: 20}}>{this.props.counter.count}</Text>
<Button title="归零" onPress={()=>this._onPressReset()}></Button>
<Button title="加" onPress={()=>this._onPressInc()}></Button>
<Button title="减" onPress={()=>this._onPressDec()}></Button>
</View>
)
}
}
const styles = StyleSheet.create({
});
const mapStateToProps = state => ({
counter: state.counter
})
export default connect(mapStateToProps)(Login);