Redux

redux是React的状态管理工具,它的工作流程如下

DC1KtU.png

Redux适合的场景

  1. 用户的使用方式复杂
  2. 不同身份的用户有不同的使用方式
  3. 用户之间可以协作
  4. 与服务器大量交互
  5. view要从多个来源获取数据
安装redux
yarn add redux
基本概念
Store

保存数据的地方,整个应用只能有一个Store。创建Store的方法为createStore

import { createStore } from 'redux'
import reducer from './reducer'
const store = createStore(reducer, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__())
export default store
State

Store 包含所有的数据,State 是某一个时间点的数据集合,获取State的方法为store.getState()

this.state = store.getState()
Action

Action 用来改变Store中的数据,action是一个对象,约定必须有一个type属性,它表示action的名称,其他属性可以任意设置

handleInputChange(e) {
  const action = {
    // action 的类型
    type: CHANGE_INPUT_VALUE,
    // 需要传递的参数
    value: e.target.value
  }

  // 调用 dispatch 方法修改 store 的值
  store.dispatch(action)
}
Reducer

Reducer接受action修改Store的请求,然后把修改后的State返回给Store,Store用Reducer返回的值替换原来的值,因此只有Store能够改变自己的内容。

import { CHANGE_INPUT_VALUE, ADD_TODO_ITEM, DELETE_TODO_ITEM } from './actionTypes'
const defaultState = {
  inputValue: '',
  list: []
}
// reducer 可以接收 state,但不能修改 state
const fn = (state = defaultState, action) => {
  if (action.type === CHANGE_INPUT_VALUE) {
    const newState = JSON.parse(JSON.stringify(state))
    newState.inputValue = action.value
    return newState
  }
  return state
}
export default fn

Reducer必须是一个纯函数,纯函数满足以下两点

  1. 给定输入输出是固定的
const fn = (state = defaultState, action) => {
  if (action.type === CHANGE_INPUT_VALUE) {
    const newState = JSON.parse(JSON.stringify(state))
    // inputValue 受到当前时间影响,所以fn不是纯函数
    newState.inputValue = new Date()
    return newState
  }
  return state
}
  1. 没有副作用
const fn = (state = defaultState, action) => {
  if (action.type === CHANGE_INPUT_VALUE) {
    const newState = JSON.parse(JSON.stringify(state))
    newState.inputValue = action.value
    // 对传入参数进行修改,因此是有副作用的
    state.inputValue = ''
    return newState
  }
  return state
}
Action Creator

一个项目可能会用到很多action,可以众多action集中到一个文件,便于进行管理

store/actionCreators.js

import { ADD_TODO_ITEM, CHANGE_INPUT_VALUE, DELETE_TODO_ITEM } from './actionTypes'

export const getInputChangeAction = (value) => ({
  type: CHANGE_INPUT_VALUE,
  value
})

Redux高级

UI组件和容器组件

将React组件划分为UI组件和容器组件,UI组件负责渲染,容器组件负责处理逻辑,这样的划分可以避免组件的代码过于庞大,也让代码逻辑更加清晰。

TodoList.js

import React, { Component } from 'react'
import 'antd/dist/antd.css'

import store from './store'
import TodoListUI from './TodoListUI'
import { getInputChangeAction, getAddItemAction, getDeleteItemAction } from './store/actionCreators'

class TodoList extends Component {
  constructor(props) {
    super(props)
    this.state = store.getState()
    this.handleInputChange = this.handleInputChange.bind(this)
    this.handleStoreChange = this.handleStoreChange.bind(this)
    this.handleBtnClick = this.handleBtnClick.bind(this)
    this.handleItemDelete = this.handleItemDelete.bind(this)
  }
  componentDidMount() {
    // 订阅 store 的变化,交给 handleStoreChange 处理
    store.subscribe(this.handleStoreChange)
  }
  componentWillUnmount() {
    store.unsubscribe(this.handleStoreChange) // 取消订阅,清理已注册的监听
  }

  render() {
    return (
      
    )
  }
  handleInputChange(e) {
    const action = getInputChangeAction(e.target.value)
    // 调用 dispatch 方法修改 store 的值
    store.dispatch(action)
  }
  handleStoreChange() {
    // 根据 store 更新 state
    this.setState(store.getState())
  }
  handleBtnClick() {
    const action = getAddItemAction()
    store.dispatch(action)
  }
  handleItemDelete(index) {
    const action = getDeleteItemAction(index)
    store.dispatch(action)
  }
}

export default TodoList

TodoListUI.js

import React, { Component } from 'react'
import { Input, Button, List } from 'antd'
class TodoListUI extends Component {
  render() {
    return (
      

TODO

( // onClick 的监听函数需要接收参数,应该修改为函数的形式 { this.props.handleItemDelete(index) }} key={index} > {item} )} />
) } } export default TodoListUI

store/actionCreators.js

import { ADD_TODO_ITEM, CHANGE_INPUT_VALUE, DELETE_TODO_ITEM } from './actionTypes'

export const getInputChangeAction = (value) => ({
  type: CHANGE_INPUT_VALUE,
  value
})

export const getAddItemAction = () => ({
  type: ADD_TODO_ITEM
})

export const getDeleteItemAction = (index) => ({
  type: DELETE_TODO_ITEM,
  index
})
无状态组件

无状态组件指的是只含有render函数的组件,一般可以将UI组件可以改写成无状态组件,可以提升一部分性能。

import React, { Component } from 'react'
import { Input, Button, List } from 'antd'

const TodoListUI = (props) => {
  return (
    

TODO

( // onClick 的监听函数需要接收参数,应该修改为函数的形式 { props.handleItemDelete(index) }} key={index} > {item} )} />
) } export default TodoListUI
Redux发送异步请求获取数据
yarn add axios

TodoList.js

componentDidMount() {
  // 订阅 store 的变化,交给 handleStoreChange 处理
  store.subscribe(this.handleStoreChange)
  axios.get('http://localhost.charlesproxy.com:3000/api/todolist').then((res) => {
    const data = res.data
    const action = initListAction(data)
    store.dispatch(action)
  })
}

你可能感兴趣的:(Redux)