react笔记(十五)—— react-redux-基本使用

136 阅读4分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第15天,点击查看活动详情

前言

大家好呀,我是L同学。在上篇文章react笔记(十四)—— redux代码执行过程中,我们学习了纯函数、Redux核心概念store、Redux 获取默认值的执行过程、Redux 代码执行过程等相关知识点。在本篇文章中,我们将学习到React-redux基本介绍、react-redux-基本使用、react-redux-useSelector、react-redux-useDispatch等相关知识点。

React-redux基本介绍

React 和 Redux 是两个独立的库,两者之间职责独立。因此,为了实现在 React 中使用 Redux 进行状态管理 ,就需要一种机制,将这两个独立的库关联在一起。这时候就用到 React-Redux 这个绑定库了。React-Redux为 React 接入 Redux,实现在 React 中使用 Redux 进行状态管理。react-redux 库是 Redux 官方提供的 React 绑定库。

react-redux-基本使用

首先安装react-redux:yarn add react-redux

import ReactDOM from 'react-dom'
import App from './App.js'
import store from './store/store.js'
import { Provider } from 'react-redux'
ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.querySelector('#root')
)

react-redux-useSelector

react-redux提供了useSelector。useSelector从Redux 的 store 中获取 状态(state) 数据。selector 函数应该是个纯函数。Provider组件依然需要使用。

import { useSelector } from 'react-redux'
import { addMore, addOne, subMore, subOne } from './store/action'
export default function App() {
  // 通过redux实现金钱管理
  // 通过store.getState() 就可以获取到store的状态
  const money = useSelector((state) => state)
  return (
    <div>
      <h1>我是根组件</h1>
      <div>当前的金钱:{money}</div>
      <div>
        <button>+1</button>
        <button>-1</button>
        <button>+5</button>
        <button>-5</button>
        <button>+10</button>
        <button>-10</button>
      </div>
    </div>
  )
}

react-redux-useDispatch

react-redux提供了useDispatch。useDispatch是修改数据的hooks。

import { useDispatch } from 'react-redux'
import { useSelector } from 'react-redux'
import { addMore, addOne, subMore, subOne } from './store/action'
export default function App() {
  // 通过redux实现金钱管理
  // 通过store.getState() 就可以获取到store的状态
  const money = useSelector((state) => state)
  const dispatch = useDispatch()
  return (
    <div>
      <h1>我是根组件</h1>
      <div>当前的金钱:{money}</div>
      <div>
        <button onClick={() => dispatch(addOne())}>+1</button>
        <button onClick={() => dispatch(subOne())}>-1</button>
        <button onClick={() => dispatch(addMore(5))}>+5</button>
        <button onClick={() => dispatch(subMore(5))}>-5</button>
        <button>+10</button>
        <button>-10</button>
      </div>
    </div>
  )
}

Reducer 的分离与合并

随着项目功能变得越来越复杂,需要 Redux 管理的状态也会越来越多。此时,有两种方式来处理状态的更新:使用一个 reducer处理项目中所有状态的更新;使用多个 reducer按照项目功能划分,每个功能使用一个 reducer 来处理该功能的状态更新。使用第二种方案(多个 reducer) ,每个 reducer 处理的状态更单一,职责更明确。此时,项目中会有多个 reducer,但是 store 只能接收一个 reducer,因此,需要将多个 reducer 合并为一根 reducer,才能传递给 store。合并方式是使用 Redux 中的 combineReducers 函数。合并后,Redux 的状态会变为一个对象,对象的结构与 combineReducers 函数的参数结构相同。比如,此时 Redux 状态为:{ a: aReducer 处理的状态, b: bReducer 处理的状态 }

虽然在使用 combineReducers 以后,整个 Redux 应用的状态变为了对象,但是,对于每个 reducer 来说,每个 reducer 只负责整个状态中的某一个值。也就是每个 reducer 各司其职,最终,由多个 reducer 合作完成整个应用状态的更新。也就是每个reducer只负责整个应用状态中的某一部分,每个 reducer 都很自私只关注自己的数据。举个例子,登录功能loginReducer 处理的状态只应该是跟登录相关的状态。个人资料profileReducer处理的状态只应该是跟个人资料相关的状态。文章列表、文章详情、文章评论 等。

import { combineReducers } from 'redux'
function money(state = 1000, action) {
  console.log('reducer执行', action)
  // 处理各种各样的action
  switch (action.type) {
    case 'addOne':
      return state + 1
    case 'subOne':
      return state - 1
    case 'addMore':
      return state + action.payload
    case 'subMore':
      return state - action.payload
    default:
      // 很重要
      return state
  }
}

function user(state = { name: 'zs', password: '123456' }, action) {
  if (action.type === 'setName') {
    return {
      ...state,
      name: action.payload
    }
  }
  return state
}

// 合并多个reducer
const rootReducer = combineReducers({
  // a 和 b指的就是模块的名字
  money,
  user
})

export default rootReducer

Action Type的使用

Action Type 指的是action 对象中 type 属性的值。Redux 项目中会多次使用 action type,比如,action 对象、reducer 函数、dispatch(action) 等。集中处理 action type,保持项目中 action type 的一致性。

处理方式:

  1. 在 store 目录中创建 actionTypes 目录或者 constants 目录,集中处理

  2. 使用常量来存储 action type

  3. action type 的值采用:'domain/action'(功能/动作)形式,进行分类处理,比如,

    • 计数器:'counter/increment' 表示 Counter 功能中的 increment 动作
    • TodoMVC:'todos/add' 表示 TodoMVC 案例中 add 动作等
    • 登录:login/getCode 表示登录获取验证码的动作;login/submit 表示登录功能
    • 个人信息:profile/get 表示获取个人资料;profile/updateName 表示修改昵称
  4. 将项目中用到 action type 的地方替换为这些常量,从而保持项目中 action type 的一致性。

export const SET_NAME = 'user/setName'
export const SUB_MORE = 'money/subMore'