react+redux
我個人認為流程如圖
index.ios.js
/*
* @author: changhuijun
* @createTime: 2017-03-20, 15:58:16 GMT+0800
* @description: description
*/
import React, {Component} from 'react';
import {
AppRegistry,
} from 'react-native';
import reducer from './classes/reducer';
import APP from './classes/mainPage'
import { createStore } from 'redux';
import { Provider } from 'react-redux';
const store = createStore(reducer);
export default class ReactWithRedux extends Component {
// Provider 包裹住 項目,則項目里面所有的 js 都可以訪問到 store
render() {
return (
<Provider store={store}>
<APP />
</Provider>
);
}
}
AppRegistry.registerComponent('ReactWithRedux', () => ReactWithRedux);
mainPage.js
/*
* 安裝第三方模塊
npm install --save redux
npm install --save react-redux
npm install --save react-router
* */
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
TouchableOpacity,
TextInput,
} from 'react-native';
import {connect} from 'react-redux';
import * as ACTION from './action'
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
});
class mainPage extends Component {
constructor(props){
super(props);
this.state={
inputText:'默認值',
};
this.onChangeText = this.onChangeText.bind(this);
}
// 點擊方法
onChangeText (){
// 調用 發送 action的方法。傳遞參數
this.props.onChangeAction(this.state.inputText);
this.setState({
inputText: '',
});
}
render() {
const {text , list } = this.props;
return (
<View style={styles.container}>
<TextInput
style={{height: 40, borderColor: 'gray', borderWidth: 1 , justifyContent: 'center'}}
onChangeText={(text) => this.setState({inputText: text})}
value={this.state.inputText}
/>
<TouchableOpacity onPress={this.onChangeText}>
<Text>點擊我,通過 redux 改變 state.text </Text>
</TouchableOpacity>
<Text>改變后的state.text值:{text}</Text>
<Text style={{marginTop: 30}}>list:</Text>
{
list.map((item, index)=>{
return <Text key={index}>{item}</Text>
})
}
</View>
);
}
}
// 映射 Redux state 到組件的屬性,reducer 改變完 state 以后,將更新過后的state 映射到這個方法
// 每次 state 的改變,都會走這個方法
//[mapStateToProps(state, [ownProps]): stateProps] (Function):
// 如果定義該參數,組件將會監聽 Redux store 的變化。
// 任何時候,只要 Redux store 發生改變,mapStateToProps 函數就會被調用。
// 該回調函數必須返回一個純對象,這個對象會與組件的 props 合并。
// 如果你省略了這個參數,你的組件將不會監聽 Redux store。
// 如果指定了該回調函數中的第二個參數 ownProps,則該參數的值為傳遞到組件的 props,而且只要組件接收到新的 props,mapStateToProps 也會被調用。
function mapStateToProps(state) {
console.log('state:'+JSON.stringify(state));
return {
text: state.text,
list:state.list,
};
}
// 映射 Redux actions 到組件的屬性
//[mapDispatchToProps(dispatch, [ownProps]): dispatchProps] (Object or Function):
// 如果傳遞的是一個對象,那么每個定義在該對象的函數都將被當作 Redux action creator,而且這個對象會與 Redux store 綁定在一起,
// 其中所定義的方法名將作為屬性名,合并到組件的 props 中。
// 如果傳遞的是一個函數,該函數將接收一個 dispatch 函數,然后由你來決定如何返回一個對象,
// 這個對象通過 dispatch 函數與 action creator 以某種方式綁定在一起(提示:你也許會用到 Redux 的輔助函數 bindActionCreators())。
// 如果你省略這個 mapDispatchToProps 參數,默認情況下,dispatch 會注入到你的組件 props 中。
// 如果指定了該回調函數中第二個參數 ownProps,該參數的值為傳遞到組件的 props,
// 而且只要組件接收到新 props,mapDispatchToProps 也會被調用。
function mapDispatchToProps(dispatch){
return{
// 真正的發送 action
onChangeAction:(text) => {
// 分發事件,reducer 接收到 action,改變state
dispatch(ACTION.CHANGE_TEXT_ACTION(text));
dispatch(ACTION.ADD_TEXT_ACTION(text));
}
}
}
// 連接 React 組件與 Redux store。
// 連接操作不會改變原來的組件類,反而返回一個新的已與 Redux store 連接的組件類。
// 我們用 react-redux 提供的 connect() 方法將“笨拙”的 Counter 轉化成容器組件。connect() 允許你從 Redux store 中指定準確的 state 到你想要獲取的組件中。這讓你能獲取到任何級別顆粒度的數據。
export default connect(mapStateToProps, mapDispatchToProps)(mainPage);
action.js
/**
* Created by mymac on 2017/5/18.
*/
// * as 是把action里面所有 export 的都import 進來, 可以使用 .屬性 訪問
import * as ACTIONTYPE from './actionType'
// 修改 state.text
export const CHANGE_TEXT_ACTION = (text) => {
return {
type: ACTIONTYPE.ACTION_CHANGE_TEXT_TYPE,
text: text,
};
};
// 添加 state.list
export const ADD_TEXT_ACTION = (text) => {
return {
type: ACTIONTYPE.ACTION_ADD_TEXT_TYPE,
text: text,
};
};
actionType.js
/**
* Created by mymac on 2017/5/18.
*/
// 修改
export const ACTION_CHANGE_TEXT_TYPE = 'CHANGE_TEXT_TYPE';
// 添加
export const ACTION_ADD_TEXT_TYPE = 'ADD_TEXT_TYPE';
reduces.js
/**
* Created by mymac on 2017/5/18.
*/
// * as 是把action里面所有 export 的都import 進來, 可以使用 .屬性 訪問
import * as ACTION from './actionType'
const initState = {
text:'默認值',
list:[],
};
/*
* 注意:
不要修改 state。 使用 Object.assign() 新建了一個副本。不能這樣使用 Object.assign(state, { visibilityFilter: action.filter }),因為它會改變第一個參數的值。你必須把第一個參數設置為空對象。你也可以開啟對ES7提案對象展開運算符的支持, 從而使用 { ...state, ...newState } 達到相同的目的。
在 default 情況下返回舊的 state。遇到未知的 action 時,一定要返回舊的 state。
Object.assign 須知
Object.assign() 是 ES6 特性,但多數瀏覽器并不支持。你要么使用 polyfill,Babel 插件,或者使用其它庫如 _.assign() 提供的幫助方法。
*
* */
export default (state = initState, action) => {
switch (action.type) {
case ACTION.ACTION_CHANGE_TEXT_TYPE :
return Object.assign({}, state, {
text: action.text
});
break;
case ACTION.ACTION_ADD_TEXT_TYPE :
let list = state.list;
list.push(action.text);
return Object.assign({}, state, {
list: list
});
break;
default:
return state;
break;
}
}
QQ20170518-180234.gif