2、创建Action
创建Store后,接下来我们来创建对应的Action,下方代码就是对应的action文件中的内容。首先创建了一个 CountActionType 的对象,功能类似于枚举,其中 "ADD" 代表加法类型,"DESC" 代表减法类型。因为该示例中是在一个Reducer中处理的两个Action,所以得用 CountActionType 类型来判断派发的是哪个Action,然后做对应的操作。
然后创建了一个 addTowNumbers 方法,该方法接收了一个参数,然后返回一个Action对象,其中Action对象的类型就是 ADD。 而下方的 descTowNumbers 方法返回的也是一个Action,该Action对应的是减法操作。稍后我们会使用到该Action。
3、创建Reducer
下方的calculateReducer方法就是我们创建的Reducer, 该方法接收两个参数,一个是State对象, 一个是Action对象。我们给State对象赋了一个默认值, 这个默认值中有两个值,一个是表示加法结果的 addResult, 另一个是表示减法结果的 descResult。
Action对象中的payload对象中有两个值,及firstNumberhe和secondNumber,表示输入的两个值。而在Reducer中通过Action的Type字段来判断是做加法操作还是减法操作。如果是Add则是加法操作,将payload中的两个值相加,然后将结果赋值给 state 中的addResult。如果是Desc的话,与Add类似,只不过做的是减法操作。
在该Reducer方法中,返回的是一个计算后端新的State。State被修改后,可以通过 Store 中的 subscribe 的方法进行监听该状态的改变。
4、AddTestView的实现
定义好Store、Action、Reducer, 接下来我们就开始定义可操作的视图了。下方的AddTestView就是上面两个计算加减法的控件。下方是具体实现的说明:
在AddTestView中的构造方法中,我们调用了 store 对象中的 subscribe 方法,传入了一个回调方法,来对Store中存储的状态进行监听,然后获取state中最新的状态,然后赋值给组件对应的State对象。
第二段核心的代码则是dispathAction了,在输入框变化后,会根据是Add还是Desc调用下方的dispatchAction方法。如果是Add, 就会调用addTowNumber方法创建一个 加法动作对应的Action。如果是减法操作的话,则会调用 descTowNumber()方法创建一个减法对应的Action对象。然后把创建好的对象,通过store.dispatch(action) 方法派发出去。
store收到 Action后就会执行对应的 Reducer方法,然后去跟进Action提供的信息修改 Store中存储的State值。当State值被修改后,就会执行 subscriber 对应的回调方法获取最新的结果值,并赋值给组件内部的State对象进行展示。
下方AddTestView的全部代码。
// 仅仅使用redux import React, { Component } from 'react'; import { Action } from 'redux'; import {Text, TouchableOpacity, View, StyleSheet, TextInput} from 'react-native'; import { store } from './store'; import {addTowNumbers, descTowNumbers, CountActionType} from './action'; const { DESC, ADD } = CountActionType; type State = { addResult: number, descResult: number }; const styles = StyleSheet.create({ textInput: { width: 60, borderRadius: 4, borderWidth: 0.5, borderColor: 'gray' }, tipText: { } }); export default class AddTestView extends Component<null, State> { addFirstNumber: string = '0'; addSecondNumber: string = '0'; descFirstNumber: string = '0'; descSecondNumber: string = '0'; constructor (props: any) { super(props); this.state = { addResult: 0, descResult: 0 }; store.subscribe(() => { const { addResult, descResult } = store.getState(); this.setState({ addResult, descResult }); }); } firstTextChange = (type) => (text) => { if (type === CountActionType.ADD) { this.addFirstNumber = text; this.dispathAddAction(); } else { this.descFirstNumber = text; this.dispathDescAction(); } } secondTextChange = (type) => (text) => { if (type === CountActionType.ADD) { this.addSecondNumber = text; this.dispathAddAction(); } else { this.descSecondNumber = text; this.dispathDescAction(); } } dispathAddAction = () => { const action = addTowNumbers({firstNumber: this.addFirstNumber, secondNumber: this.addSecondNumber}); store.dispatch(action); } dispathDescAction = () => { const action = descTowNumbers({firstNumber: this.descFirstNumber, secondNumber: this.descSecondNumber}); store.dispatch(action); } calculate = (type) => { const calculateText = type === CountActionType.ADD ? '+' : '-'; const result = type === CountActionType.ADD ? this.state.addResult : this.state.descResult; return ( <View style={{flexDirection: 'row'}}> <TextInput style={styles.textInput} defaultValue={'0'} onChangeText = {this.firstTextChange(type)}/> <Text> {calculateText} </Text> <TextInput style={styles.textInput} defaultValue={'0'} onChangeText = {this.secondTextChange(type)}/> <Text> = </Text> <Text>{result}</Text> </View> ); } render () { return ( <View style={{ justifyContent: 'center', alignItems: 'center' }}> {this.calculate(CountActionType.ADD)} {this.calculate(CountActionType.DESC)} </View> ); } }