redux的使用
react-native,react,react-redux,react-navigaition,redux-thunk,redux-persist
三大原则
react-redux 连接react和redux
- import { connect,Provider } from 'react-redux'
connet([mapStateToProps],[mapDispatchToProps],[mergeProps])(App)
mapStateToProps: 基于全局的state,选择我们要注入的props
不同的组件分开connec
- function select(state){
- return{
- // 把state.todos注入,读取方法: this.props.visibleTodo
- visibleTodo: state.todos
- }
- }
- const todoApp connect(select)(App)
- // export default todoApp
- // store = "balabala"
- <Provider store={store}>
- <todoApp />
- </Provider>
redux三剑客
- // 先确定一下初始状态(状态表示的格式)
- export default {
- money: 0,lastJob:'no job'
- }
ACTION
定义动作,比如抢劫银行、搬砖,但是怎么抢怎么搬还是reducer来定
- /**
- * Created by liuyiman on 2017/7/3.
- */
- // 定义一个menoy+的action
- function addmoney(money){
- return {
- // 可以用一个文件管理type,之所以是type是因为我的reducer要根据这个来判断
- type: 'ADD_MONEY',money
- }
- }
- function setLastJob(job){
- return {
- type: 'SET_JOB',job
- }
- }
- // 定义一个赚钱的方式1 ,抢劫银行
- export function robBank(){
- return (dispatch,getState) => {
- // 赚一百万
- let { earn } = getState()
- dispatch(addmoney(earn.money + 1000000))
- return dispatch(setLastJob('robber'))
- }
- }
- // 定义一个赚钱的方式2,建材转移者
- export function moveBrick(){
- return (dispatch,getState) => {
- console.log('s',getState())
- let { earn } = getState()
- // 赚一块钱
- dispatch(addmoney( earn.money + 1 ))
- dispatch(setLastJob('brick mover'))
- }
- }
- // 破产,数据清零
- export function goBroke() {
- return {
- type: 'BROKE',money: 0,job:'broke'
- }
- }
reducers
描述action如何改变store(in fact state)
- import { combineReducers } from 'redux'
- import initializeState from './initializeState'
- // 定义一个reducer
- function earn( state = initializeState,action ) {
- switch (action.type) {
- case 'ADD_MONEY':
- return{
- ...state,money:action.money
- }
- case 'SET_JOB':
- return{
- ...state,lastJob:action.job
- }
- case 'BROKE':
- return{
- ...state,money:action.money,lastJob:action.job
- }
- default:
- return state
- }
- }
- export default earn
store
不同的组件可以 connet 到不同的 store
- import { createStore,applyMiddleware,compose,combineReducers } from 'redux'
- import thunkMidlleware from 'redux-thunk'
- import earn from './reducers'
- import { persistStore,autoRehydrate} from 'redux-persist'
- import { AsyncStorage } from 'react-native'
- // base reducer
- let baseReducers = {
- earn: earn
- }
- /*
- * 考虑到后面要将react-navigation的reducer加进来,使用redux-persist,所以写了这个helper
- * const store = configStore(reducers)()
- * */
- const configStore = function (reducers = {}) {
- const rootReducer = combineReducers({
- ...baseReducers,...reducers
- })
- return function (_options = {}) {
- const store = createStore(
- rootReducer,_options.initialState,compose(
- applyMiddleware(thunkMidlleware),autoRehydrate()
- )
- )
- const options = {
- storage: AsyncStorage,blacklist: _options.blacklist
- }
- persistStore(store,options)
- return store
- }
- }
- export default configStore
more
中间件 middleware
redux-thunk
使dispatch可以接受函数说作为参数,使异步的action可以被触发
- // 无论killSomeOne是Action create还是普通的返回{}的action
- this.props.dispath(killSomeOne('vincent'))
redux-persist
本地保存store状态(react-native 本地缓存),可以设置白名单黑名单自动保存等等,特别好用
- /*
- * 考虑到后面要将react-navigation的reducer加进来,使用redux-persist,options)
- return store
- }
- }
- export default configStore
react-navigation + redux
- import React,{ Component } from 'react';
- import {
- AppRegistry,StyleSheet,Text,View,Button
- } from 'react-native';
- // navigation
- import { TabNavigator,addNavigationHelpers,StackNavigator } from 'react-navigation'
- // for connect redux and react
- import { Provider,connect } from 'react-redux'
- import configStore from './redux/store'
- // import actions
- import {moveBrick,robBank,goBroke} from './redux/actions'
- // initialState
- import initialState from './redux/store'
- // 赚钱页面
- class Earn extends Component {
- constructor(props) {
- super(props)
- }
- render(){
- const { earn,dispatch } = this.props
- console.log( 'saa',initialState,earn )
- return(
- <View style={styles.container}>
- <Text>先赚一个亿!</Text>
- <Text>my money$:{earn.money}</Text>
- <Text>my last job:{earn.lastJob}</Text>
- <Button title="rob a bank" onPress={() => dispatch(robBank())}/>
- <Button title="move some Brick" onPress={() => dispatch(moveBrick())}/>
- <Text>价格指导:搬砖 -> $1; 打劫 -> $1000000</Text>
- <Button title="broke" onPress={() => dispatch(goBroke())}/>
- </View>
- )
- }
- }
- // 传入 earn页面的redux
- const earnSelect = function (state) {
- return{
- earn: state.earn
- }
- }
- // 连接,吧earn上面的select传入earn的props里面
- const ConnnetedEarn = connect(earnSelect)(Earn)
- // tab navigation的另一个页面
- class Screen extends Component{
- constructor(props){
- super(props)
- }
- render() {
- const { navigate } = this.props.navigation
- return(
- <View style={styles.container}>
- <Text>SCREEN!</Text>
- <Button title="to stack2" onPress={() => {navigate('Stack2')}}/>
- </View>
- )
- }
- }
- // 注册一个tag navigator
- const AppNav = TabNavigator({
- 'earn':{
- screen: ConnnetedEarn
- },'screen': {
- screen: Screen
- }
- })
- // stack navigation 的页面
- class Stack2 extends Component {
- constructor(props){
- super(props)
- }
- render(){
- const {navigate} = this.props.navigation
- return (
- <View style={styles.container}>
- <Text>Stack2</Text>
- <Button title="TO APP NAV" onPress={() => navigate('screen')}/>
- </View>
- )
- }
- }
- /*
- * 注册stack
- * 一个是 上面的 tag navigation的页面
- * 另一个是 上面的 stack2
- * */
- const StackNav = StackNavigator({
- App:{
- screen: AppNav,title: 'app'
- },Stack2: {
- screen: Stack2,title: 'stack2'
- }
- })
- const navInitialState = StackNav.router.getStateForAction(AppNav.router.getActionForPathAndParams('screen'))
- const navReducer = (state = navInitialState,action) => {
- console.log('state:',state)
- let nextState = StackNav.router.getStateForAction(action,state);
- console.log('action',action)
- return nextState || state
- }
- /*
- * 加入navReducer,生成store
- * */
- const store = configStore({
- nav: navReducer
- })({
- blacklist:['nav']
- })
- /*
- * stack app
- * 利用addNavigationHelper吧navigation传进去
- * */
- class App extends Component{
- render(){
- return(
- <StackNav navigation={addNavigationHelpers({
- dispatch: this.props.dispatch,state: this.props.nav
- })} />
- )
- }
- }
- /*
- * 把nav传进去
- * */
- function select(state) {
- console.log('state',state)
- return {
- nav: state.nav
- }
- }
- /*
- * connect connect!
- * */
- const ConnectedApp = connect(select)(App)
- // 加上 provider和store
- class reduxLearn extends Component {
- render() {
- return (
- <Provider store={store}>
- <ConnectedApp/>
- </Provider>
- );
- }
- }
- const styles = StyleSheet.create({
- container: {
- flex: 1,justifyContent: 'center',alignItems: 'center',backgroundColor: '#F5FCFF',},welcome: {
- fontSize: 20,textAlign: 'center',margin: 10,instructions: {
- textAlign: 'center',color: '#333333',marginBottom: 5,});
- // 注册
- AppRegistry.registerComponent('reduxLearn',() => reduxLearn);