React Redux应用示例详解
admin
2024-01-20 21:03:01
0

一 React-Redux的应用

1.学习文档

  • 英文文档: Redux - A predictable state container for JavaScript apps. | Redux
  • 中文文档: Redux 中文官网 - JavaScript 应用的状态容器,提供可预测的状态管理。 | Redux 中文官网
  • Github: GitHub - reduxjs/redux: Predictable state container for JavaScript apps

2.Redux的需求

  1. 状态的集中管理
  2. 任意页面与组件之间的数据传递
  3. 状态管理的可预测
  4. 数据的本地化缓存提升性能

说明:

随着对JavaScript单页应用程序的要求变得越来越复杂,我们的代码必须比以前更多地处理状态。此状态可以包括服务器响应和缓存数据,以及本地创建的尚未保存到服务器的数据。 UI状态的复杂性也在增加,因为我们需要管理活动路线,选定标签,旋钮,分页控件等。 管理这个不断变化的状态是困难的。

如果一个模型可以更新另一个模型,那么一个视图可以更新一个模型,该模型会更新另一个模型,而这又可能导致另一个视图更新。在某种程度上,您不再理解您的应用程序会发生什么情况,因为您已经失去了对其状态的何时,为何和如何的控制。

当系统不透明且不确定时,很难重现错误或添加新功能。 好像这还不够糟糕,请考虑新的要求在前端产品开发中变得常见。作为开发人员,我们需要处理乐观的更新,服务器端渲染,在执行路由转换之前获取数据等等。

我们发现自己试图去处理一个我们以前从来没有处理过的复杂问题,而且我们不可避免地提出这个问题:是放弃的时候了吗?答案是不。

这种复杂性很难处理,因为我们正在混合两个对人类头脑非常难以推理的概念:突变和异步性。我把它们叫做曼托斯和可乐。两者在分离方面都很出色,但它们一起造成一团糟。像React这样的库试图通过去除异步和直接DOM操作来解决视图层中的这个问题。但是,管理数据的状态由您决定。这是Redux进入的地方。

3.什么是Redux

  • redux是一个独立专门用于做状态管理的JS库(不是react插件库)
  • 它可以用在react、angular、vue等项目中,但基本与react配合使用
  • 作用:集中式管理react应用中多个组件共享的状态

4.什么情况下需要使用redux

  1. 总体原则: 大型项目状态管理复杂才用
  2. 某个组件的状态,需要共享
  3. 某个状态需要在任何地方都可以拿到
  4. 一个组件需要改变全局状态
  5. 一个组件需要改变另一个组件的状态

二、最新React-Redux 的流程

安装Redux Toolkit

# NPM
npm install @reduxjs/toolkit
# Yarn
yarn add @reduxjs/toolkit

创建一个 React Redux 应用

官方推荐的使用 React 和 Redux 创建新应用的方式是使用官方 Redux+JS 模版或Redux+TS 模板,它基于Create React App,利用了Redux Toolkit和 Redux 与 React 组件的集成.

# Redux + Plain JS template
npx create-react-app my-app --template redux
# Redux + TypeScript template
npx create-react-app my-app --template redux-typescript

Redux 核心库​

Redux 核心库同样有 NPM 软件包,可与模块捆绑器或 Node 应用程序一起使用,安装方式如下:

# NPM
npm install redux
# Yarn
yarn add redux

基础示例

应用的整体全局状态以对象树的方式存放于单个store。 唯一改变状态树(state tree)的方法是创建action,一个描述发生了什么的对象,并将其dispatch给 store。 要指定状态树如何响应 action 来进行更新,你可以编写纯reducer函数,这些函数根据旧 state 和 action 来计算新 state。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

import { createStore } from 'redux'

/**

 * 这是一个 reducer 函数:接受当前 state 值和描述“发生了什么”的 action 对象,它返回一个新的 state 值。

 * reducer 函数签名是 : (state, action) => newState

 *

 * Redux state 应该只包含普通的 JS 对象、数组和原语。

 * 根状态值通常是一个对象。 重要的是,不应该改变 state 对象,而是在 state 发生变化时返回一个新对象。

 *

 * 你可以在 reducer 中使用任何条件逻辑。 在这个例子中,我们使用了 switch 语句,但这不是必需的。

 *

 */

function counterReducer(state = { value: 0 }, action) {

  switch (action.type) {

    case 'counter/incremented':

      return { value: state.value + 1 }

    case 'counter/decremented':

      return { value: state.value - 1 }

    default:

      return state

  }

}

// 创建一个包含应用程序 state 的 Redux store。

// 它的 API 有 { subscribe, dispatch, getState }.

let store = createStore(counterReducer)

// 你可以使用 subscribe() 来更新 UI 以响应 state 的更改。

// 通常你会使用视图绑定库(例如 React Redux)而不是直接使用 subscribe()。

// 可能还有其他用例对 subscribe 也有帮助。

store.subscribe(() => console.log(store.getState()))

// 改变内部状态的唯一方法是 dispatch 一个 action。

// 这些 action 可以被序列化、记录或存储,然后再重放。

store.dispatch({ type: 'counter/incremented' })

// {value: 1}

store.dispatch({ type: 'counter/incremented' })

// {value: 2}

store.dispatch({ type: 'counter/decremented' })

// {value: 1}

Redux Toolkit 示例

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

import { createSlice, configureStore } from '@reduxjs/toolkit'

const counterSlice = createSlice({

  name: 'counter',

  initialState: {

    value: 0

  },

  reducers: {

    incremented: state => {

      // Redux Toolkit 允许在 reducers 中编写 "mutating" 逻辑。

      // 它实际上并没有改变 state,因为使用的是 Immer 库,检测到“草稿 state”的变化并产生一个全新的

      // 基于这些更改的不可变的 state。

      state.value += 1

    },

    decremented: state => {

      state.value -= 1

    }

  }

})

export const { incremented, decremented } = counterSlice.actions

const store = configureStore({

  reducer: counterSlice.reducer

})

// 可以订阅 store

store.subscribe(() => console.log(store.getState()))

// 将我们所创建的 action 对象传递给 `dispatch`

store.dispatch(incremented())

// {value: 1}

store.dispatch(incremented())

// {value: 2}

store.dispatch(decremented())

// {value: 1}

三、使用教程

安装Redux Toolkit和React-Redux​

添加 Redux Toolkit 和 React-Redux 依赖包到你的项目中:

创建 Redux Store​

创建src/app/store.js文件。从 Redux Toolkit 引入configureStoreAPI。我们从创建一个空的 Redux store 开始,并且导出它:

app/store.js

1

2

3

4

import { configureStore } from '@reduxjs/toolkit'

export default configureStore({

  reducer: {}

})

npm install @reduxjs/toolkit react-redux

上面代码创建了 Redux store ,并且自动配置了 Redux DevTools 扩展 ,这样你就可以在开发时调试 store。

为React提供Redux Store​

创建 store 后,便可以在 React 组件中使用它。 在 src/index.js 中引入我们刚刚创建的 store , 通过 React-Redux 的包裹起来,并将 store 作为 prop 传入。

index.js

1

2

3

4

5

6

7

8

9

10

11

12

import React from 'react'

import ReactDOM from 'react-dom'

import './index.css'

import App from './App'

import store from './app/store'

import { Provider } from 'react-redux'

ReactDOM.render(

  

    

  ,

  document.getElementById('root')

)

创建Redux State Slice​

创建src/features/counter/counterSlice.js文件。在该文件中从 Redux Toolkit 引入createSliceAPI。

创建 slice 需要一个字符串名称来标识切片、一个初始 state 以及一个或多个定义了该如何更新 state 的 reducer 函数。slice 创建后 ,我们可以导出 slice 中生成的 Redux action creators 和 reducer 函数。

Redux 要求我们通过创建数据副本和更新数据副本,来实现不可变地写入所有状态更新。不过 Redux ToolkitcreateSlicecreateReducer在内部使用 Immer 允许我们编写“可变”的更新逻辑,变成正确的不可变更新。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

features/counter/counterSlice.js

import { createSlice } from '@reduxjs/toolkit'

export const counterSlice = createSlice({

  name: 'counter',

  initialState: {

    value: 0

  },

  reducers: {

    increment: state => {

      // Redux Toolkit 允许我们在 reducers 写 "可变" 逻辑。它

      // 并不是真正的改变状态值,因为它使用了 Immer 库

      // 可以检测到“草稿状态“ 的变化并且基于这些变化生产全新的

      // 不可变的状态

      state.value += 1

    },

    decrement: state => {

      state.value -= 1

    },

    incrementByAmount: (state, action) => {

      state.value += action.payload

    }

  }

})

// 每个 case reducer 函数会生成对应的 Action creators

export const { increment, decrement, incrementByAmount } = counterSlice.actions

export default counterSlice.reducer

将Slice Reducers添加到Store 中​

下一步,我们需要从计数切片中引入 reducer 函数,并将它添加到我们的 store 中。通过在 reducer 参数中定义一个字段,我们告诉 store 使用这个 slice reducer 函数来处理对该状态的所有更新。

app/store.js

1

2

3

4

5

6

7

import { configureStore } from '@reduxjs/toolkit'

import counterReducer from '../features/counter/counterSlice'

export default configureStore({

  reducer: {

    counter: counterReducer

  }

})

在React组件中使用Redux状态和操作​

现在我们可以使用 React-Redux 钩子让 React 组件与 Redux store 交互。我们可以使用useSelector从 store 中读取数据,使用useDispatchdispatch actions。创建包含组件的src/features/counter/Counter.js文件,然后将该组件导入App.js并在中渲染它。

features/counter/Counter.js

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

import React from 'react'

import { useSelector, useDispatch } from 'react-redux'

import { decrement, increment } from './counterSlice'

import styles from './Counter.module.css'

export function Counter() {

  const count = useSelector(state => state.counter.value)

  const dispatch = useDispatch()

  return (

    

      

        

          aria-label="Increment value"

          onClick={() => dispatch(increment())}

        >

          Increment

        

        {count}

        

          aria-label="Decrement value"

          onClick={() => dispatch(decrement())}

        >

          Decrement

        

      

    

  )

}

现在,每当你点击”递增“和“递减”按钮。

  • 会 dispatch 对应的 Redux action 到 store
  • 在计数器切片对应的 reducer 中将看到 action 并更新其状态
  • 组件将从 store 中看到新的状态,并使用新数据重新渲染组件

你学到了什么​

这是关于如何通过 React 设置和使用 Redux Toolkit 的简要概述。 回顾细节:

总结

使用configureStore创建 Redux store

  • configureStore接受reducer函数作为命名参数
  • configureStore使用的好用的默认设置自动设置 store

为 React 应用程序组件提供 Redux store

  • 使用 React-Redux组件包裹你的
  • 传递 Redux store 如

使用createSlice创建 Redux "slice" reducer

  • 使用字符串名称、初始状态和命名的 reducer 函数调用“createSlice”
  • Reducer 函数可以使用 Immer 来“改变”状态
  • 导出生成的 slice reducer 和 action creators

在 React 组件中使用 React-ReduxuseSelector/useDispatch钩子

  • 使用useSelector钩子从 store 中读取数据
  • 使用useDispatch钩子获取dispatch函数,并根据需要 dispatch actions

相关内容

热门资讯

安卓系统弹出窗口问题,安卓系统... 手机里的安卓系统突然弹出窗口,是不是让你心头一紧,手忙脚乱?别急,今天就来和你聊聊这个让人头疼的安卓...
安卓系统加苹果战队,科技竞技的... 你知道吗?在科技的世界里,有一场特别的较量正在悄然上演。那就是安卓系统和苹果战队的对决!这两大操作系...
miui与安卓系统关系,深度定... 亲爱的读者,你是否曾在使用手机时,对那熟悉的MIUI界面感到亲切又好奇?今天,就让我们一起揭开MIU...
安卓原生系统手机哪些,探索安卓... 你有没有想过,为什么你的手机总是那么流畅,那么强大?这背后,可是有一个默默无闻的英雄——安卓原生系统...
安卓系统cpu天梯图,性能比拼... 你有没有发现,手机里的安卓系统,就像是我们的好朋友,每天都在默默无闻地工作着。而它的心脏,也就是CP...
安卓系统通知时间,掌握生活节奏... 你有没有发现,手机里的安卓系统通知时间有时候会让人有点头疼呢?有时候它准时得像军号,有时候又懒洋洋得...
安卓系统默认安装位置,默认安装... 你有没有发现,每次新买一台安卓手机,打开它的时候,那些默认安装的APP总是占据着固定的位置?是不是好...
安卓系统内存优化模式,高效运行... 手机用久了是不是感觉越来越卡?别急,今天就来给你揭秘安卓系统内存优化模式的秘密,让你的手机焕发新生!...
零信任软件安卓系统,零信任软件... 你知道吗?在科技飞速发展的今天,手机已经成为了我们生活中不可或缺的一部分。而在这其中,安卓系统凭借其...
怎样更改安卓系统时间,安卓系统... 手机时间不对了?别急,我来教你怎样更改安卓系统时间,让你手机上的时间瞬间回到正轨!一、直接调整系统时...
鸿蒙系统离不开安卓,基于安卓的... 你知道吗?最近在科技圈里,有一个话题可是引起了不小的讨论呢!那就是鸿蒙系统与安卓的关系。很多人都在问...
安卓系统怎么重启应用,安卓系统... 手机里的安卓应用突然卡住了,是不是让你头疼不已?别急,今天就来教你怎么轻松重启安卓系统中的应用,让你...
安卓系统开启远程登录,安卓系统... 你有没有想过,即使你不在家,也能轻松管理你的安卓设备呢?没错,就是安卓系统开启远程登录!这可是个超级...
黑域安卓系统4.0,创新功能与... 亲爱的读者们,你是否对安卓系统有所好奇?今天,我要带你深入探索一个神秘而独特的存在——黑域安卓系统4...
安卓系统基础教程,从入门到精通 你有没有想过,你的安卓手机里那些神奇的软件和功能是怎么来的呢?其实,这一切都离不开安卓系统的基础。今...
安卓系统盒子停服,回顾辉煌历程 你有没有发现,最近你的安卓系统盒子突然有点不对劲?是不是觉得它变得有点“懒”,不再像以前那样活泼了呢...
安卓系统怎么下蝙蝠,安卓系统下... 你有没有想过,在安卓手机上下载蝙蝠APP,竟然也能成为一门学问呢?没错,就是那个让你随时随地畅游网络...
安卓系统能播放蓝光,安卓系统轻... 你有没有想过,你的安卓手机或者平板,竟然能播放那些高清到让人惊艳的蓝光电影呢?没错,就是那种画质细腻...
汽车系统识别到安卓,智能驾驶新... 你知道吗?最近汽车界可是掀起了一股新潮流呢!那就是汽车系统识别到安卓,这可不是简单的兼容,而是深度融...
工程业务系统安卓版,助力项目管... 你知道吗?最近我在手机上发现了一个超级实用的工程业务系统安卓版,简直让我爱不释手!这款应用不仅功能强...