深入了解 Redux:JavaScript 应用状态管理的完整指南

Redux 是一个流行的 JavaScript 状态管理库,它为应用程序提供了可预测的状态容器。无论您是新手还是经验丰富的开发者,都可以通过 Redux 来更好地管理应用程序的状态。

在本文中,我们将深入探讨 Redux 的核心概念、工作原理以及最佳实践,帮助您更好地理解和运用 Redux。

1. 为什么选择 Redux
  • -React管理不断变化的state是非常困难的,需要通过constructor去定义state,要通过this.setState去 修改这个state。
  • React是在视图层帮助我们解决了DOM的渲染过程,但是State依然是留给我们自己来管理。之前学 习过的组件传值props、context等等,
  • 当没有使用redux的时候我们实现兄弟组件传值是比较麻烦的,代码很复杂冗余。
2. Redux 核心概念
  • -Actions Actions 是描述发生了什么的纯对象。它们是应用发送数据到 store 的唯一方式。一般通过 type 字段来指明 action 的类型。
  • Reducers
    Reducers 指定了应用状态的变化如何响应 actions 并且发送到 store。它是一个纯函数,接收先前的状态和一个 action,并返回新的状态。
  • Store
    Store 是应用状态的单一来源。它负责:
    保存应用的状态
    允许通过 getState() 方法获取状态
    允许通过 dispatch(action) 方法更新状态
    允许通过 subscribe(listener) 方法注册监听器
  • 单一数据源(Single Source of Truth)
    整个应用的 state 被储存在一棵 object tree 中,并且这个 object tree 只存在于唯一一个 store 中。
  • 不可变性(State is Read-Only)
    State 是只读的,任何修改必须通过纯函数来进行。这意味着在修改 state 时需要返回新的 state 对象,而不是直接修改原始的 state。
  • 单向数据流
    整个应用中的 state 遵循严格的单向数据流。任何的数据流回馈都必须经过 action -> dispatcher -> store -> view 这样的流程。
    这些核心概念构成了 Redux 库的基础,为开发者提供了一种清晰的、一致的模式来处理应用的状态。通过深入理解这些概念,开发者可以更好地利用 Redux 来构建复杂的前端应用程序。
3. 数据流向
  • 触发 Action

    • 当应用程序中的某个部分需要发起一些操作时(比如用户交互或者异步请求完成),会触发一个 action。这个 action是一个包含描述要执行操作的纯对象,通常具有一个 type 属性来指明操作类型,并可能携带其他相关数据。
  • Dispatch Action

    • 通过使用 Redux store 中提供的 dispatch(action) 方法,将 action 分发到 store 中。
  • Reducer 处理 Action

    • Store 中已经注册的 reducers 会根据接收到的 action 来处理状态的变化。根据 action 的类型和携带的数据,相应的
      reducer 将计算出新的状态并返回。
  • Store 更新

    • 当 reducer 返回新的状态后,Redux 的 store 会被更新为最新的状态。
  • 订阅状态更新

    • 在 React 应用中,通常会使用 react-redux 提供的 useSelector 钩子或者 connect 方法来订阅
      store 中 state 的更新。
  • 组件重新渲染

    • 由于状态的更新,与 store 中相关联的组件(通过 useSelector 或 connect)会感知到状态的变化,然后进行重新渲染。

代码:

下载依赖

yarn add react-redux redux

在store.js创建仓库

import { legacy_createStore as createStore } from 'redux'
const initialState = {} // 初识状态
// reducers
const reducer = (state = initialState, action) => { // reducer可以接受state,但是绝对不能改变state}
// 创建仓库
export default createStore(reducer)

在index项目入口文件引入store注入到根组件中

......
// 引入redux
import store from './redux/store'
import { Provider } from 'react-redux'
......
root.render(
		<Provider store={store}>
			<App />
		</Provider>
	);
);

编写action
Action 创建函数 就是生成 action 的方法。“action” 和 “action 创建函数” 这两个概念很容易混在一起,
使用时最好注意区分。

// store/index.js
const CHANGE_MSG = 'CHANGE_MSG'
export const a_changeMsg = payload => {
	return {
		type: CHANGE_MSG,
		payload
	}
}

编写reducer

// store/index.js
// reducer可以接受state,但是绝对不能改变state
const CHANGE_MSG = 'CHANGE_MSG'
const initialState = {
	msg: '你好,李焕英'
}
......
const reducer = (state = initialState, action) => {
	switch(action.type) {
		case CHANGE_MSG:
			return { ...state, msg: action.payload }
		default:
			return state
	}
}

组件使用useSelector和useDispatch来操作redux

// Redux.jsx
import React from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { a_changeMsg } from './store'
export default function Redux() {
	const msg = useSelector(state => state.msg) // 使用hooks中的useSelector获取redux仓库中的state
	const dispatch = useDispatch() // 使用hooks中的useDispatch调用redux=>action来修改数据
	return (
		<>
			<h1>{ msg }</h1>
			<button onClick={ () => dispatch(a_changeMsg('你好,贾玲她妈')) }>修改</button>
		</>
	)
}
4. 异步操作处理
  • 如何处理异步操作,使用 thunk 或者 saga 等中间件进行异步 action 的处理。
  • 如果redux中的状态是通过异步请求接口进行更新的
// store/index.js
import { legacy_createStore as createStore } from 'redux'
......
export const a_asyncChangeMsg = payload => {
	setTimeout(() => { // 模拟异步请求接口
		return {
			type: CHANGE_MSG,
			payload
		}
	}, 0)
}
......
export default createStore(reducer)
// Redux.jsx
import React from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { a_asyncChangeMsg } from './store'
export default function Redux() {
	const msg = useSelector(state => state.msg) // 使用hooks中的useSelector获取redux仓库中的state
	const dispatch = useDispatch() // 使用hooks中的useDispatch调用redux=>action来修改数据
	return (
		<>
			<h1>{ msg }</h1>
			<button onClick={ () => dispatch(a_asyncChangeMsg('你好,贾玲她妈')) }>修改</button>
		</>
	)
}
  • 在redux的工作流中,reducer是纯函数,内部不能进行异步操作。那么我们只能将异步的操作放入在
    actionCreator中进行,但是如果直接这样写会报错哦
  • 因为actions必须为普通对象,但实际上却是一个函数,你可能需要在创建store的时候添加一个中间件,比如redux-thunk
  • actions必须为普通对象,但实际上却是一个函数,你可能需要在创建store的时候添 加一个中间件,比如redux-thunk
5. 与 React 结合使用
  • 如何在 React 应用中使用 Redux,并介绍 react-redux 这个库的使用方法。
  • 将redux代码改造一下
  • 安装redux-thunk
- `yarn add redux-thunk`
  • 修改store.js,引入中间件
import { legacy_createStore as createStore, applyMiddleware } from 'redux'
import { thunk } from 'redux-thunk' // 处理redux异步任务的中间件
......
// applyMiddleware 应用中间件,对store中的dispatch方法进行增强
export default createStore(reducer, applyMiddleware(thunk))
  • 修改actions,返回一个函数
export const a_asyncChangeMsg = payload => {
	return (dispatch, getState) => {
		setTimeout(() => {
			dispatch(a_changeMsg('你好,贾玲她妈'))
		}, 1000)
	}
}
  • 测试异步代码
import React from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { a_asyncChangeMsg } from './store'
export default function Redux() {
	const msg = useSelector(state => state.msg) // 使用hooks中的useSelector获取redux仓库中的state
	const dispatch = useDispatch() // 使用hooks中的useDispatch调用redux=>action来
	修改数据
	return (
	<>
	<h1>{ msg }</h1>
	<button onClick={ () => dispatch(a_asyncChangeMsg()) }>修改</button>
	</>
	)
}
6. 常见问题
  • 过度使用 Redux
    有时候开发者会倾向于将所有的状态都存储在 Redux 中,这可能导致过度复杂化应用。在设计时应该权衡哪些状态适合放在 Redux 中,而哪些状态可以由组件本地管理。

  • 过多的 Boilerplate 代码

  • 传统的 Redux 存在大量的样板代码,如定义 action 类型、编写 reducer等。虽然可以通过使用辅助工具来减少这些重复性代码,但需要谨慎使用,并评估是否真正需要 Redux 来管理状态。

  • 性能问题
    当应用状态变得非常庞大时,Redux 可能造成性能瓶颈。合理地使用 selectors、避免不必要的重新渲染和状态更新、以及对状态树进行规范化都是解决性能问题的方法。

  • 异步操作处理
    虽然 Redux 自身只处理同步操作,但很多应用需要异步操作(如网络请求)。处理异步操作时,需要使用中间件或异步 action 创建函数。

结语
  • 总结 Redux 的重要概念,并鼓励读者进一步深入学习。
    在本篇博客中,我们将深入 Redux 的方方面面,旨在帮助读者全面理解 Redux 并能够在实际项目中应用它。通过本文,您将获得对 Redux 的深刻理解,并能够更加自信地使用它来管理应用程序的状态。
  • 16
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值