react之redux的学习

为什么需要redux

  1. 管理的状态越来越多,越来越复杂。
  2. 状态包括服务器返回、缓存的数据、用户操作产生的数据、UI的展示状态等。
  3. 管理不断变化的state是非常困难的。
    一个状态的变化引起另一个状态的变化,UI也会引起状态的变化。
  4. react帮助我们管理视图,state需要我们自己管理。
  5. 帮助我们管理state的容器。

核心理念

  1. store
  2. action
  3. reducer

三大原则

  • 单一数据源
  1. 整个项目的state存在一个object tree中,并且这个object tree之存储在store中
  2. redex可以创建多个store,但是不利于维护
  3. 单一的数据源可以让项目state变的方便维护、追踪、修改。
  • state是只读的
  1. 唯一修改方法是触发action
  2. 被集中处理,按照严格的顺序执行,不需要担心竞态问题
  • 纯函数修改

简单使用

单文件

const redux = require('redux')
// 初始化数据
const initialState = {
  counter: 0
}
// reducer
function reducer(state = initialState, action) {
  switch (action.type) {
    case "+":
      return { ...state, counter: state.counter + 1 }
      break;
    case "-":
      return { ...state, counter: state.counter - 1 }
      break;
    case "+N":
      return { ...state, counter: state.counter + action.num }
      break;
    case "-N":
      return { ...state, counter: state.counter - action.num }
      break;
    default:
      return state
      break;
  }
}
// 创建store
const store = redux.createStore(reducer)
// 订阅修改
store.subscribe(()=>{
  console.log('改变',store.getState().counter);
})
// action
const action1 = { type: '+' }
const action2 = { type: '-' }
const action3 = { type: '+N', num: 8 }
const action4 = { type: '-N', num: 6 }
// 触发action
store.dispatch(action1)
store.dispatch(action2)
store.dispatch(action3)
store.dispatch(action4)

真实项目的使用方法,会将state、action等分开写。
一般分为index.js、reducer.js、createActions.js、constants.js 4个文件。
index.js 入口文件

import redux from 'redux'
import reducer from './reducer.js'
const store = redux.createStore(reducer)
export default store

constants.js 定义常量的文件

export const ADD_NUMBER = 'ADD_NUMBER'
export const SUB_NUMBER = 'SUB_NUMBER'

createActions.js 创建action的文件

import { ADD_NUMBER,SUB_NUMBER } from './constants.js'
export const addAction = num => ({
    type: ADD_NUMBER,
    num
})
export const subAction = num => ({
  type: SUB_NUMBER,
  num
})

reducer.js 执行action到state的文件

import { SUB_NUMBER, ADD_NUMBER } from './constants.js'
const defaultState = {
  counter: 0
}
function reducer(state = defaultState, action) {
  switch (action.type) {
    case SUB_NUMBER:
      return { ...state, counter: state.counter - action.num }
      break;  
    case ADD_NUMBER:
      return { ...state, counter: state.counter + action.num }
      break;
    default:
      return state
      break;
  }
}
export default reducer

异步Action

使用中间件redux-thunk,添加异步Action

import redux,{applyMiddleware} from 'redux'
const store = redux.createStore(reducer,applyMiddleware(thunk))

通过react-redux连接UI组件

react-redux中有容器组件和UI组件。
UI组件就是我们编写的UI样式,容器组件就是UI组件的父级,通过高阶组件的原理绑定props到UI组件。
代码示例


import { addAction,subAction } from '../../store/createActions'
// import store from '../../store/index'
import React, { PureComponent } from 'react'
import { connect } from 'react-redux'
class Home extends PureComponent {
  add(){
    this.props.jia(1)
  }
  sub(){
    this.props.jian(2)
  }
  render() {
    return (
      <div>
        <h3>{this.props.counter.counter}</h3>
        <button onClick={e=>this.add()}>+</button>
        <button onClick={e=>this.sub()}>-</button>
      </div>
    )
  }
}
const mapStateToProps = state=>({counter:state})

const mapDispatchToProps = {
  jia:addAction,
  jian:subAction
}
export default connect(mapStateToProps,mapDispatchToProps)(Home)

通过react-redux提供的`Provider组件传递store数据

import { Provider } from 'react-redux'
   <Provider store={store}>
    <App/>
   </Provider>

其中,react-redux提供了实时渲染UI数据的功能,避免使用如下代码进行监听。

 store.subscribe(()=>{
   ReactDOM.render(<App />,document.getElementById('root'));
 })

redux-devtools使用

引入redux-devtools-extension

yarn add redux-devtools-extension
import {composeWithDevTools} from 'redux-devtools-extension'
const store = createStore(reducer,composeWithDevTools())

你可能感兴趣的:(React,react)