阅读 270

react-native之redux状态管理

一、前言

react-navtive的状态管理需要使用redux,以下是redux工作的流程图

image-20200213143633201

React组件如果要改变状态,

  1. 就需要让调用ActionCreators创建出一个action对象,
  2. 然后再调用store.dispatch(action对象),
  3. store就会将(previousState,action)传递给Reducers,Reducers处理完成后,就返回newState,
  4. store再将state更新给React组件

形象化,比喻为我要去图书管借书这件事

  1. ActionCreators 创造出一条语句:我要借什么书?
  2. 图书管理员(store)接收了我的请求(dispatch(action对象))
  3. 图书管理员将请求(previousState,action)输入到电脑的记录本 (Reducers),记录本记录完后,就返回新的的记录本
  4. 图书管理员(store)于是给了我(React Component)书(state)

二、安装环境

npm install --save redux
npm install --save react-redux
npm install --save-dev redux-devtools
复制代码

redux(必选)

react-redux(必选)

redux作者为了方便在react上使用redux开发等一个用户react上的redux库redux-devtools(可选)redux开发者工具支持热加载、action重放、自定义UI等功能

三、创建相应的文件

├── store
│   ├── reducer.js
│   ├── actionCreator.js
│   ├── index.js
复制代码

创建store

// store/inde.js
import {createStore} from "redux"
import reducer from "./reducer"
const store = createStore(reducer)
export default store
复制代码

创建reducer

// store/reducer.js
const defaultState = {
  token:""
}
export default (state=defaultState,action)=>{
  if(action.type==="token"){
    let newState = {...state}
    newState.token=action.value
    return newState
  }
  return state
}
复制代码

创建constants

// store/constants.js
export const TOKEN = "token"
复制代码

创建actionCreator

// store/actionCreator
export const setToken =(token){
  return {
    type:"token",
    value:token
  }
}
复制代码

四、组件获取与更改state

获取state

import store from './store/index'
class demo extends Component{
  constructor(props){
    super(props)
    this.state = store.getState()
	}
	render(){
    return (
			<View>{this.state.token}</View>
    )
  }
}

复制代码

更改state

import {setToken} from "./store/actionCreators"
import store from './store/index'
class demo extends Component{
  constructor(props){
    super(props)
	}
  changToken = (token)=>{
    const action = setToken(token);// 创建action对象
    store.dispatch(action)
  }
	render(){
    return (
			<Button 
        title="设置Token"
        onPress={()=>{
          this.changeToken("abc")
        }}
      />
    )
  }
}
复制代码

五、使用第三方库redux-thunk

原生的redux只能同步处理state,当我们想要异步去处理state时,就没有办法了、比如用户发送登陆请求后,服务器会返回token,此时我们就需要将token保存到state里,网络请求是异步的,于是我们需要使用可以异步更改state的redux-thunk

image-20200213154034030

安装

npm install --save redux-thunk
复制代码

在创建store时使用redux-thunk中间件

// store/index.js
import { createStore, applyMiddleware } from 'redux';
import thunk from "redux-thunk"
import reducer from "./reducer"
const store = createStore(reducer,applyMiddleware(thunk))
export default store
复制代码

在actionCreator中创建异步函数

// store/actionCreators
import {login} from "../api/login"//login是登陆的网络请求
export const setToken = (token)=>({
  type:"token",
  value:token
})
export const Login = ({phone,password})=>{
  return dispatch=>{
    login({phone,password}).then(res=>{
      if(res.code==200){
        const action = setToken(res.data)
        dispatch(action)
      }
    })
  }
}
复制代码

在组件中调用异步函数

import {Login} from "../store/actionCreators"
import store from "../store"
class demo extends Component {
  render(){
    return <View onClick={this.handleLogin}>登陆</View>
  }
  handLogin=()=>{
    const action = Login({phone:1234,password:1234})
    store.dispatch(action)// 当store发现action时一个函数时,会先执行这个函数
  }
}
复制代码

六、视图组件绑定

  • <Provider>组件:这个组件需要包裹在整个组件树的最外层。这个组件让跟组件的所有子孙组件能够轻松的使用connect()方法绑定store
  • connect():这是react-redux提供的一个方法,如果一个组件想要响应状态的变化,就把自己作为参数传给connect()的结果,connect()方法会处理与store绑定的细节,并通过selector确定该绑定store中哪一部分的数据
  • selector:这是你自己编写的一个函数,这个函数声明了你的组件需要整个store中的哪一部分数据作为自己的props
  • dispatch:每当你想要改变应用中的状态时,你就要dispatch一个action,这也是唯一改变状态的方法

react-redux提供以下API

  • Provider
  • connect

Provider

为了在全局都能使用conect(),必须将根组件嵌套在<Provider></Provider>

import {Provider} from "react-redux"
import store from "./store"
function App(){
  return(
		<Provider store={store}>
      <AppIndex></AppIndex>
    </Provider>
  )
}
复制代码

connect

API原型:connect([mapStateToProps],[mapDispatchToProps],[mergeProps],[options])

react-redux提供了connect函数,connect是一个高阶函数,首先传入mapStateToPropsmapDispatchToProps,然后返回一个生产Component的函数wrapWithConnect,然后再将真正的Component作为参数传入wrapWithConnect(MyComponent),这样就生产出一个经过包裹的Connect 组件:

如:export default connect(mapStateToProps)(HomePage)

在组件中使用connect

import {connect} from "react-redux"
import actionCreators from "../store/actionCreators"
class deom extends Component{
 render(){
   reuturn (
   	<View>token:{this.props.token}</View>
     <View onClick={this.props.Login({phone:1234,password:1234})}>登陆</View>
   )
 }
}
const mapStateToProps = state=>{
 return {
   token:state.token
 }
}
const mapDispatchToProps = dispatch=>{
 return {
   Login({phone,password}){
     const action = actionCreators.Login({phone,password})
     dispatch(action)
   }
 }
}
复制代码

mapStateToProps是将store中state映射到组件的props中去,即可以通过this.props.to ken获取到store中的存储的token

mapDispatchToProps返回的是一个对象,这个对象里有许多方法,这些方法里可以调用 dispatch,然后这些方法全部都映射到组件的props中去,既可以通过this.props.方法调用

七、使用actionTypes

action对象一般都是如下:

{
  type:"token",
  value:"1432"
}
复制代码

在reducer中,这样判断action的type

export default function (state=defaultState,action){
  if(action.type==="token"){
    ....
  }
}
复制代码

从上面我们可以看到,type都是一个字符串类型,我们在开发过程中,字符串写错了,程序会运行错误,但系统不会报错,为了解决这个问题,我们可以将字符串变成变量

可以在store文件夹下新建actionTypes来存储type类型

├── store
│   ├── reducer.js
│   ├── actionTypes.js
│   ├── actionCreator.js
│   ├── index.js
复制代码
// store/actionTypes
export const TOKEN = "token"
复制代码
// store/actionCreator
import * as actionTypes from "./actionTypes"
export const setToken = (token)=>({
  type:actionTypes.TOKEN,
  value:token,
})
复制代码
// store/reducer
import * as actionTypes from "./actionTypes"
export default (state=defaultState,action)=>{
  if(action.type===actionTypes.TOKEN)
}
复制代码

这样,当我们变量名写错时,系统就会给予警告

八、使用combineReducers

一个app可能有用户信息,历史消息,设备信息等等,如果我们把所有信息都放在一个reducer中就显得太臃肿不好管理,所以我们可以使用redux提供的combineReducers来合并多个reducer

// store/reducer
import {combineReducers} from "redux"
import {reducer as UserReducer} from "../page/UserLogin/store"
import {reducer as DeviceReducer} from "../page/Device/store"
export default combineReducers({
    user:UserReducer,
  	device:DeviceReducer
})
复制代码

在组件中可以这样使用

mapStateToProps=(state)=>{
  return {
    token:state.user.token,
    deviceNum:state.device.number
  }
}
复制代码

结语

赠人玫瑰,手有余香。各位看官,觉得不错请点个赞,如有错漏处,还请指正呀

作者:胡志武

时间:2020/02/13

关注下面的标签,发现更多相似文章
评论