redux的运用
react-native, react, react-redux, react-navigaition, redux-thunk, redux-persist
用户发出action, reducer函数算出新的state, view从新衬着
三大原则
单一数据源,应用props的情势向下流传(react数据流决议)
state只读,经由过程action修正
经由过程纯函数reducer来修正组件状况,reducer是形貌action行动的纯函数
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
对store.dispatch的从新定义
在发出action和实行reducer之间,添加了其他功用
redux-thunk
使dispatch能够接收函数说作为参数,使异步的action能够被触发
// 不管killSomeOne是Action create照样一般的返回{}的action
this.props.dispath(killSomeOne('vincent'))
redux-persist
当地保留store状况(react-native 当地缓存),能够设置白名单黑名单自动保留等等,迥殊好用
/*
* 考虑到背面要将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
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);