Redux三大原则
1.单一数据源
整个应用的state被存储在唯一的object tree中,也就是存于store中。
2.state是只读的
改变state的唯一方式就是发起Action。
3.使用纯函数来修改state
也就是编写reducer,它是为了描述Action是如何改变state tree的。
Action
actIon是一个用于描述发生事件的普通对象。action内用一个字符串type来表示将要执行的动作,一般它是一个常量。这里用一个单独的文件ActionTypes来存放。
constants/ActionTypes.js
export const ADD_NUM = 'ADD_NUM'; export const REDUCE_NUM = 'REDUCE_NUM'; export const UPDATE_TEXT = 'UPDATE_TEXT';
action/index.js
import * as types from '../constants/ActionTypes'; export function addTodo(num){ return { type:types.ADD_NUM, num:num } } export function reduceTodo(num){ return { type:types.REDUCE_NUM, num:num } } export function updateText(text){ return { type:types.UPDATE_TEXT, text:text } }
Reducer
reducer是一些纯函数(任意两次相同的输入,输出也相同),它接收旧的state和action,返回新的state。
保持 reducer 纯净非常重要。永远不要在 reducer 里做这些操作:
1、修改传入参数;
2、执行有副作用的操作,如 API 请求和路由跳转;
3、调用非纯函数,如 Date.now() 或 Math.random()。
1、修改传入参数;
2、执行有副作用的操作,如 API 请求和路由跳转;
3、调用非纯函数,如 Date.now() 或 Math.random()。
reducers/counter.js
import * as types from '../constants/ActionTypes'; const initialState = { num:0, }; export default function counter(state = initialState,action){ switch(action.type){ case types.ADD_NUM: state.num = action.num; return Object.assign({}, state); break; case types.REDUCE_NUM: state.num = action.num; return Object.assign({}, state); break; default: return Object.assign({}, state); break; } }
import * as types from '../constants/ActionTypes'; const initialState = { text:'', }; export default function todos(state = initialState,action){ switch(action.type){ case types.UPDATE_TEXT: state.text = action.text; return Object.assign({}, state); break; default: return Object.assign({}, state); break; } }
通过combineReducers合并两个reducer
reducers/index.js
import {combineReducers} from 'redux'; import todos from './toDo'; import counter from './counter'; const rootReducers = combineReducers({ todos, counter, }); export default rootReducers;
Store
store就是把action和reducers联系到一起的对象,store有以下职责。
- 维持应用的 state;
- 提供
getState()
方法获取 state; - 提供
dispatch(action)
方法更新 state; - 通过
subscribe(listener)
注册监听器; - 通过
subscribe(listener)
返回的函数注销监听器。
创建store,
createStore的第二个参数是可选的,用于设置state的初始状态。
使用combineReducers将多个reducer合并成为一个,然后导入,并传递给createStroe
import {createStore} from 'redux'; import reducers from './app/reducers'; let store = createStore(reducers);
入口组件index.android.js
import React, { Component } from 'react'; import { AppRegistry, } from 'react-native'; import {createStore} from 'redux'; import { Provider } from 'react-redux'; import reducers from './app/reducers'; import App from './app/containers/App'; class ReduxDemo extends Component { render() { let store = createStore(reducers); return ( <Provider store={store}> <App/> </Provider> ); } } AppRegistry.registerComponent('ReduxDemo', () => ReduxDemo);
视图组件App.js
connect的作用是将视图和store连接起来。
在视图里面调通过dispatch来调用action。
import React, {Component} from 'react'; import{ View, Text, TouchableOpacity, StyleSheet, Dimensions, } from 'react-native'; import {connect} from 'react-redux'; import {addTodo,reduceTodo,updateText} from '../action/index'; const {width, height} = Dimensions.get('window'); class App extends Component{ constructor(props) { super(props); } render(){ const {dispatch,counter,todos} = this.props; var {num} = counter; var {text} = todos; return ( <View style={styles.container}> <TouchableOpacity style={styles.row} onPress={()=>{dispatch(addTodo(++num))}}> <Text>点击就加1</Text> </TouchableOpacity> <TouchableOpacity style={styles.row} onPress={()=>{dispatch(reduceTodo(--num))}}> <Text>点击就减1</Text> </TouchableOpacity> <TouchableOpacity style={styles.row} onPress={()=>{dispatch(updateText("ReactNative"))}}> <Text>修改Text值</Text> </TouchableOpacity> <View style={[styles.row,styles.text]}> <Text>当前num值是:<Text style={styles.red}>{num}</Text>,当前的Text值是:<Text style={styles.red}>{text}</Text></Text> </View> </View> ); } } const styles = StyleSheet.create({ container:{ flex:1, justifyContent:'center', alignItems:'center', backgroundColor:'#fff', }, row:{ height:40, width:width, marginTop:10, borderWidth:StyleSheet.hairlineWidth, borderColor:'#aaa', backgroundColor:'#eee', justifyContent:'center', alignItems:'center', }, text:{ backgroundColor:'#f0f0f0', alignItems:'flex-start', paddingLeft:10, }, red:{ color:'red', } }); //这是你自己编写的一个函数。这个函数声明了你的组件需要整个 store 中的哪一部分数据作为自己的 props。 //这个函数的作用是确定哪些 Redux 全局的 state 是我们组件想要通过 props 获取的 function mapStateToProps(state){ const {todos,counter} = state; return { todos, counter, } } export default connect(mapStateToProps)(App);