51工具盒子

依楼听风雨
笑看云卷云舒,淡观潮起潮落

React项目:如何优雅使用Redux中的react-redux

redux是用于数据状态管理,而react是一个视图层面的库。

如果将两者连接在一起,可以使用官方推荐react-redux库,其具有高效且灵活的特性。

react-redux将组件分成:

  • 容器组件:存在逻辑处理

  • UI 组件:只负责现显示和交互,内部不处理逻辑,状态由外部控制

通过redux将整个应用状态存储到store中,组件可以派发dispatch行为actionstore

其他组件通过订阅store中的状态state来更新自身的视图
React 实际上只是 UI 框架,通过 JSX 生成动态 dom 渲染 UI,没有架构、没有模板、没有设计模式、没有路由、也没有数据管理。所以需要借助其他工具。

redux

npm install redux --save

什么是 redux ?

ReduxJavaScript 状态容器,提供可预测化的状态管理。可以理解为全局数据状态管理工具,用来做组件通信等。

为什么使用 redux ?

当没有使用 redux 时兄弟组件间传值将很麻烦,代码很复杂冗余。使用 redux 定义全局单一的数据 Store,可以自定义 Store 里面存放哪些数据,整个数据结构也是自己清楚的。

redux 工作流 ?

image.png

  • store:推送数据的仓库
  • reducer:帮助 store 处理数据的方法(初始化、修改、删除)
  • actions:数据更新的指令
  • react 组件(UI):订阅 store 中的数据

redux 用法:

import { createStore } from 'redux'

/*
 * 这是一个 reducer,形式为 (state, action) => state 的纯函数。描述了 action 如何把 state 转变成下一个 state。
 * state 的形式取决于你,可以是基本类型、数组、对象、甚至是 Immutable.js 生成的数据结构。
 * 当 state 变化时需要返回全新的对象,而不是修改传入的参数。
 */
function counter(state = 0, action) {
  switch (action.type) {
  case 'INCREMENT':
    return state + 1
  case 'DECREMENT':
    return state - 1
  default:
    return state;
  }
}

// 创建 Redux store 来存放应用的状态
// API 是 { subscribe, dispatch, getState }
const store = createStore(counter);

// 可以手动订阅更新,也可以事件绑定到视图层。
store.subscribe(() =>
  const sotreState = store.getState()
  ......
)

// 改变内部 state 惟一方法是 dispatch 一个 action。
store.dispatch({ type: 'INCREMENT' })
store.dispatch({ type: 'DECREMENT' })

redux 三大原则:

单一数据源:整个应用的 state 存放在唯一的一个 store 中。store.getState()

state 是只读的,唯一改变 state 的方法就是触发 action,action 是一个用于描述已发生事件的普通对象。

store.dispatch({
  type: 'COMPLETE_TODO',
  index: 1
})

使用纯函数来执行修改(reducer:接收先前的 state 和 action,并返回新的 state)。

function visibilityFilter(state = 'SHOW_ALL', action) {
    switch (action.type) {
      case 'SET_VISIBILITY_FILTER':
        return action.filter
      default:
        return state
    }
  }
 
  function todos(state = [], action) {
    switch (action.type) {
      case 'ADD_TODO':
        return [
          ...state,
          {
            text: action.text,
            completed: false
          }
        ]
      case 'COMPLETE_TODO':
        return state.map((todo, index) => {
          if (index === action.index) {
            return Object.assign({}, todo, {
          completed: true
            })
          }
          return todo
        })
      default:
        return state
    }
  }
 
  import { combineReducers, createStore } from 'redux'
  const reducer = combineReducers({ visibilityFilter, todos })
  const store = createStore(reducer)

React-Redux

npm install react-redux --save

React-ReduxRedux 的官方 React 绑定库。它能够使你的 React 组件从 Redux store 中读取数据,并且向 store 分发 actions 以更新数据

React-Redux 将所有组件分成两大类:UI 组件和容器组件。UI 组件负责 UI 的呈现,容器组件负责管理数据和逻辑。

  1. UI 组件:只负责 UI 的呈现,不带有任何业务逻辑;没有状态(即不使用 this.state 这个变量);所有数据都由参数 this.props 提供;不使用任何 ReduxAPI
  2. 容器组件:负责管理数据和业务逻辑,不负责 UI 的呈现;带有内部状态;使用 ReduxAPI

React-Redux 规定,所有的 UI 组件都由用户提供,容器组件则是由 React-Redux 自动生成。也就是说,用户负责视觉层,状态管理则是全部交给它。

connect()

import { connect } from 'react-redux'
const VisibleTodoList = connect(mapStateToProps, mapDispatchToProps)(TodoList)

上面 VisibleTodoList 便是 UI 组件 TodoList 通过 connect 方法自动生成的容器组件。
connect 方法接受两个参数:mapStateToPropsmapDispatchToProps。它们定义了 UI 组件的业务逻辑。前者负责输入逻辑,即将 state 映射到 UI 组件的参数 props,后者负责输出逻辑,即将用户对 UI 组件的操作映射成 Action

mapStateToProps()

const mapStateToProps = (state) => {
    return {
      todos: getVisibleTodos(state.todos, state.visibilityFilter)
}

mapStateToProps 是一个函数,它接受 state 作为参数,返回一个对象。这个对象有一个 todos 属性,代表 UI 组件的同名参数,后面的 getVisibleTodos 也是一个函数,可以从 state 算出 todos 的值。
mapStateToProps 建立一个从(外部的)state 对象到(UI 组件的)props 对象的映射关系。执行后应该返回一个对象,里面的每一个键值对就是一个映射。

mapDispatchToProps()

mapDispatchToProps 用来建立 UI 组件的参数到 store.dispatch 方法的映射。它定义了哪些用户的操作应该当作 Action,传给 Store。它可以是一个函数,也可以是一个对象。

是函数则会得到 dispatchownProps(容器组件的 props 对象)两个参数。

const mapDispatchToProps = (dispatch, ownProps) => {
    return {
      onClick: () => {
        dispatch({
          type: 'SET_VISIBILITY_FILTER',
          filter: ownProps.filter,
        })
      }
    }
}

是一个对象,它的每个键名也是对应 UI 组件的同名参数,键值应该是一个函数,会被当作 Action creator ,返回的 Action 会由 Redux 自动发出。

const mapDispatchToProps = {
    onClick: (filter) => {
      type: 'SET_VISIBILITY_FILTER',
      filter: filter
    };
  }

<Provider> 组件

connect 方法生成容器组件以后,需要让容器组件拿到 state 对象,才能生成 UI 组件的参数。

React-Redux 提供 Provider 组件,使整个 app 访问到 Redux store 中的数据 即state。

// src/index.tsx
import React from 'react'
import ReactDOM from 'react-dom'
import reportWebVitals from './reportWebVitals'
import { Provider } from 'react-redux'
import store from './redux/store'
import App from './App'

ReactDOM.render(
    <React.StrictMode>
        <Provider store={store}>
            <App />
        </Provider>
    </React.StrictMode>,
    document.getElementById('root')
)

reportWebVitals()


赞(0)
未经允许不得转载:工具盒子 » React项目:如何优雅使用Redux中的react-redux