第13节-redux

119 阅读2分钟

redux

  • 数据管理模型,跟React没有关系
  • 三大原则
    • 单一数据源(所有的数据在一个对象里面)
    • state是只读的
    • 使用纯函数执行和修改

最基本的redux用法

// => store/index.js
import { createStore } from 'redux'

function reducer(state, action) {
  // state就是数据源,action是一个带type属性的普通对象
  state = state || {
    name: '沫沫',
    age: 18
  }

  switch(action.type) {
    case 'changeName':
      state.name = action.nnn
      break;
    case 'changeAge':
      state.age = action.aaa
      break;   
  }
  return {
    ...state
  }
}

let store = createStore(reducer)

export default store
  • 使用
import React, { Component } from 'react'
import store from './index'

console.log(store)

export default class App extends Component {
  componentDidMount() {
    // 监听state的更新,添加一个回调函数
    store.subscribe(() => {
      console.log('数据更新了')
      // 调用视图更新,可能会出现state更新了视图没有更新的情况
      this.setState({})
    })
  }
  render() {
    // getState是获取state数据源的
    let state = store.getState()
    console.log(state)
    return (
      <div>
        <h1>{state.name} --- { state.age }</h1>
        <button onClick={() => {
          store.dispatch({
            type: 'changeName',
            nnn: '瑞瑞'
          })
        }}>changeName</button>
        <button onClick={() => {
          store.dispatch({
            type: 'changeAge',
            aaa: 19
          })
        }}>changeAge</button>
      </div>
    )
  }
}

store的项目处理

实际开发会根据不同的功能用不同的reducer

  • 多个reducer的情况我们需要合并reducer
import { createStore, combineReducers } from 'redux'
import {
  CHANGE_NAME,
  CHANGE_AGE,
  CHANGE_COLOR
} from './actionTypes'

function reducer(state, action) {
  // state就是数据源,action是一个带type属性的普通对象
  state = state || {
    name: '沫沫',
    age: 18
  }

  switch(action.type) {
    case CHANGE_NAME:
      state.name = action.nnn
      break;
    case CHANGE_AGE:
      state.age = action.aaa
      break;   
  }
  return {
    ...state
  }
}

function ColorReducer(state, action) {
  state = {
    color: 'red'
  }
  if(action.type === CHANGE_COLOR) {
    state.color = action.color
  }

  return {
    ...state
  }
}

// 合并reducer
let rootReducer = combineReducers({
  userInfo: reducer,
  colorInfo: ColorReducer
})

let store = createStore(rootReducer)

export default store
  • action的type在实际工作中是会用常量来指定的
// => actionTypes.js
export const CHANGE_NAME = 'CHANGE_NAME'
export const CHANGE_AGE = 'CHANGE_AGE'
export const CHANGE_COLOR = 'CHANGE_COLOR'
  • actions.js保存我们所需要的action的对象
    • acttion必须是返回type属性的对象,默认情况是不能在这里调用请求的
    • 这里如果像调用请求,需要一个中间件redux-thunk
    • npm i redux-thunk
import {
  CHANGE_NAME,
  CHANGE_COLOR,
  CHANGE_AGE
} from "./actionTypes";

export function changeName(name) {
  return function (dispatch, getState) {
    console.log(arguments)//=> dispatch, getState
    // thunk中间件 可以让dispatch 接收一个函数作为 action
    // 这个函数 会接收到对应 dispatch
    // 其实 thunk 是让dispatch 执行的是把自身触发的reducer的功能转接给了对应的函数
    // 说白了派发在这里执行了
    // fetch('/ccc').then(data => {
    //   dispatch({
    //     type: CHANGE_NAME,
    //     nnn: name
    //   })
    // })
    new Promise((resolve, reject) => {
      resolve(1)
    }).then(res => {
      dispatch({
        type: CHANGE_NAME,
        nnn: name
      })
    })
  }
}

export function changeAge(age) {
  return {
    type: CHANGE_AGE,
    aaa: age
  }
}

export function changeColor(color) {
  return {
    type: CHANGE_COLOR,
    color
  }
}
  • 使用
    • 因为合并了reducer
    • 在派发的时候也需要指定是哪个reducer执行,所有的reducer都会执行
import React, { Component } from 'react'
import store from './index'

import {
  changeAge,
  changeName,
  changeColor
} from './actions'

export default class App extends Component {
  componentDidMount() {
    // 监听state的更新,添加一个回调函数
    store.subscribe(() => {
      console.log('数据更新了')
      // 调用视图更新
      this.setState({})
    })
  }
  render() {
    // getState是获取state数据源的
    let state = store.getState()
    console.log(state)
    return (
      <div style={{color: state.colorInfo.color}}>
        <h1>{state.userInfo.name} --- { state.userInfo.age }</h1>
        <button onClick={() => {
          store.dispatch(changeName('瑞瑞'))
        }}>changeName</button>
        <button onClick={() => {
          store.dispatch(changeAge(19))
        }}>changeAge</button>
        <button onClick={() => {
          store.dispatch(changeColor('yellow'))
        }}>改颜色</button>
      </div>
    )
  }
}

image.png