Redux—JavaScript 应用程序的可预测状态容器

Redux—JavaScript 应用程序的可预测状态容器

2022-10-10 0 889
资源编号 44985 最近更新 2022-10-10
¥ 0人民币 升级VIP
立即下载 注意事项
下载不了?请联系网站客服提交链接错误!
增值服务: 安装指导 环境配置 二次开发 模板修改 源码安装

本期推荐的 Redux是JavaScript 应用程序的可预测状态容器。

Redux—JavaScript 应用程序的可预测状态容器

Redux它可以帮助您编写行为一致、在不同环境(客户端、服务器和本机)中运行并且易于测试的应用程序。最重要的是,它提供了出色的开发人员体验,例如实时代码编辑与时间旅行调试器相结合。您可以将 Redux 与React或任何其他视图库一起使用。它很小(2kB,包括依赖项),但有一个庞大的插件生态系统可用。

Redux Toolkit是我们官方推荐的编写 Redux 逻辑的方法。它围绕着 Redux 核心,并包含我们认为对于构建 Redux 应用程序至关重要的包和功能。Redux Toolkit 构建在我们建议的最佳实践中,简化了大多数 Redux 任务,防止常见错误,并使编写 Redux 应用程序更容易。

核心概念

想象一下,您的应用程序的状态被描述为一个普通对象。例如,待办事项应用程序的状态可能如下所示:

{
  todos: [{
    text: 'Eat food',
    completed: true
  }, {
    text: 'Exercise',
    completed: false
  }],
  visibilityFilter: 'SHOW_COMPLETED'
}

这个对象就像一个“模型”,只是没有设置器。这是为了让代码的不同部分不能随意改变状态,导致难以重现的错误。

要更改状态中的某些内容,您需要调度一个操作。动作是一个简单的 JavaScript 对象(注意我们没有引入任何魔法?),它描述了发生的事情。以下是一些示例操作:

{ type: 'ADD_TODO', text: 'Go to swimming pool' }
{ type: 'TOGGLE_TODO', index: 1 }
{ type: 'SET_VISIBILITY_FILTER', filter: 'SHOW_ALL' }

强制将每个更改都描述为一个操作,让我们清楚地了解应用程序中正在发生的事情。如果某事发生了变化,我们就知道它为什么会发生变化。行动就像已经发生的事情的面包屑。最后,为了将状态和动作联系在一起,我们编写了一个名为 reducer 的函数。同样,它并没有什么神奇之处——它只是一个将状态和动作作为参数的函数,并返回应用程序的下一个状态。为大型应用程序编写这样的函数会很困难,因此我们编写较小的函数来管理部分状态:

function visibilityFilter(state = 'SHOW_ALL', action) {
  if (action.type === 'SET_VISIBILITY_FILTER') {
    return action.filter
  } else {
    return state
  }
}

function todos(state = [], action) {
  switch (action.type) {
    case 'ADD_TODO':
      return state.concat([{ text: action.text, completed: false }])
    case 'TOGGLE_TODO':
      return state.map((todo, index) =>
        action.index === index
          ? { text: todo.text, completed: !todo.completed }
          : todo
      )
    default:
      return state
  }
}

我们编写了另一个reducer,通过调用这两个reducer来获取相应的状态键来管理我们应用程序的完整状态:

function todoApp(state = {}, action) {
  return {
    todos: todos(state.todos, action),
    visibilityFilter: visibilityFilter(state.visibilityFilter, action)
  }
}

这基本上是 Redux 的全部思想。请注意,我们没有使用任何 Redux API。它附带了一些实用程序来促进这种模式,但主要思想是你描述你的状态如何随着时间的推移更新以响应动作对象,你编写的 90% 的代码只是纯 JavaScript,没有使用 Redux它本身、它的 API 或任何魔法。

安装Redux

Redux Toolkit 包括 Redux 核心,以及我们认为对于构建 Redux 应用程序至关重要的其他关键包(例如 Redux Thunk 和 Reselect)。
它可以作为 NPM 上的一个包与模块捆绑器或 Node 应用程序一起使用:

# NPM
npm install @reduxjs/toolkit

# Yarn
yarn add @reduxjs/toolkit

它也可以作为 UMD 构建使用,可以从unpkg 上的dist文件夹加载。UMD 构建使 Redux Toolkit 可用作window.RTK全局变量。

Redux

# NPM
npm install redux

# Yarn
yarn add redux

配套

很可能,您还需要React 绑定开发人员工具

npm install react-redux
npm install --save-dev @redux-devtools/core

请注意,与 Redux 本身不同,Redux 生态系统中的许多包不提供 UMD 构建,因此我们建议使用WebpackBrowserify等 CommonJS 模块捆绑器以获得最舒适的开发体验。

创建一个 React Redux

使用 React 和 Redux 启动新应用程序的推荐方法是使用官方 Redux+JS 模板Redux+TS 模板进行Create React App,它利用了Redux Toolkit和 React 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

配置您的商店

首先,让我们看一下index.js我们创建商店的原始文件:

import React from 'react'
import { render } from 'react-dom'
import { Provider } from 'react-redux'
import { createStore } from 'redux'
import rootReducer from './reducers'
import App from './components/App'

const store = createStore(rootReducer)

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

在这段代码中,我们将 reducer 传递给 ReduxcreateStore函数,该函数返回一个store对象。然后我们将此对象传递给react-redux Provider组件,该组件在组件树的顶部呈现。

这确保了每当我们通过 连接到应用程序中的 Redux 时,react-redux connect我们的组件都可以使用商店。

扩展 Redux

大多数应用程序通过添加中间件或存储增强器来扩展其 Redux 存储的功能(注意:中间件很常见,增强器不太常见)。中间件为 Redux 函数增加了额外的dispatch功能;增强器为 Redux 存储添加了额外的功能。

我们将添加两个中间件和一个增强器:

  • redux-thunk中间件,它允许简单的异步使用调度。
  • 一个中间件,它记录分派的动作和产生的新状态。
  • 一个增强器,它记录减速器处理每个动作所花费的时间。
npm install redux-thunk

中间件

const logger = store => next => action => {
  console.group(action.type)
  console.info('dispatching', action)
  let result = next(action)
  console.log('next state', store.getState())
  console.groupEnd()
  return result
}

export default logger

增强器

const round = number => Math.round(number * 100) / 100

const monitorReducerEnhancer =
  createStore => (reducer, initialState, enhancer) => {
    const monitoredReducer = (state, action) => {
      const start = performance.now()
      const newState = reducer(state, action)
      const end = performance.now()
      const diff = round(end - start)

      console.log('reducer process time:', diff)

      return newState
    }

    return createStore(monitoredReducer, initialState, enhancer)
  }

export default monitorReducerEnhancer

让我们将这些添加到我们现有的index.js.

  • 首先,我们需要 importredux-thunk加上我们的loggerMiddlewareand monitorReducerEnhancer,再加上 Redux 提供的两个额外的函数:applyMiddlewareand compose。
  • 然后,我们使用applyMiddleware创建一个商店增强器,它将我们的loggerMiddleware和应用thunkMiddleware到商店的调度功能。
  • 接下来,我们将composenewmiddlewareEnhancer和 our组合monitorReducerEnhancer成一个函数。
  • 这是必需的,因为您只能将一个增强器传递到createStore. 要使用多个增强器,您必须首先将它们组合成一个更大的增强器,如本例所示。
  • 最后,我们将这个新composedEnhancers函数createStore作为它的第三个参数传入。注意:我们将忽略的第二个参数允许您将状态预加载到存储中。
import React from 'react'
import { render } from 'react-dom'
import { Provider } from 'react-redux'
import { applyMiddleware, createStore, compose } from 'redux'
import thunkMiddleware from 'redux-thunk'
import rootReducer from './reducers'
import loggerMiddleware from './middleware/logger'
import monitorReducerEnhancer from './enhancers/monitorReducer'
import App from './components/App'

const middlewareEnhancer = applyMiddleware(loggerMiddleware, thunkMiddleware)
const composedEnhancers = compose(middlewareEnhancer, monitorReducerEnhancer)

const store = createStore(rootReducer, undefined, composedEnhancers)

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

学习资源

Redux 文档旨在教授 Redux 的基本概念,并解释在实际应用程序中使用的关键概念。但是,文档不能涵盖所有内容。令人高兴的是,还有许多其他很棒的资源可用于学习 Redux。我们鼓励您查看它们。其中许多涵盖的主题超出了文档的范围,或者以其他可能更适合您的学习方式的方式描述了相同的主题。

React、Redux 和 Typescript 简介:Redux 维护者 Mark Erikson 的幻灯片集,涵盖了 React、Redux 和 TypeScript 的基础知识。Redux 主题包括 store、reducers、中间件、React-Redux 和 Redux Toolkit。

https://blog.isquaredsoftware.com/2020/12/presentations-react-redux-ts-intro/

Redux 教程:概述和演练:Tania Rascia 编写良好的教程,快速解释了 Redux 的关键概念,并展示了如何组合一个基本的 Redux + React 应用程序使用 vanilla Redux 和 Redux Toolkit。

https://www.taniarascia.com/redux-react-guide/

Redux 初学者 – 学习Redux的大脑友好指南:使用 Redux Toolkit 和 React-Redux 构建一个小型 todo 应用程序,包括数据获取。

https://www.freecodecamp.org/news/redux-for-beginners-the-brain-friendly-guide-to-redux/

使用 Redux Toolkit 和 Typescript 让 Redux 变得简单:一个有用的教程,展示了如何一起使用 Redux Toolkit 和 TypeScript 来编写 Redux应用程序,以及 RTK 如何简化典型的 Redux 使用。

https://www.mattbutton.com/redux-made-easy-with-redux-toolkit-and-typescript/

基本示例

应用程序的整个全局状态存储在单个store内的对象树中。更改状态树的唯一方法是创建一个action,一个描述发生了什么的对象,并将其分派到 store。要指定状态如何更新以响应操作,您编写纯reducer函数,根据旧状态和操作计算新状态。

import { createStore } from 'redux'

/**
* 这是一个reducer - 一个接受当前状态值和描述“发生了什么”的动作对象的函数,并返回一个新的状态值。
* reducer 的函数签名是:(state, action) => newState 
* 
* Redux 状态应该只包含普通的 JS 对象、数组和原语。
* 根状态值通常是一个对象。重要的是你不应该改变状态对象,而是在状态改变时返回一个新对象。
* 
* 你可以在 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
  }
}

// 创建一个 Redux 存储来保存你的应用程序的状态。
// 它的 API 是 { subscribe, dispatch, getState }。
let store = createStore(counterReducer)

// 您可以使用 subscribe() 来更新 UI 以响应状态更改。
// 通常你会使用视图绑定库(例如 React Redux)而不是直接订阅()。
// 可能还有其他用例对订阅也有帮助。

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

// 改变内部状态的唯一方法是调度一个动作。
// 这些动作可以被序列化、记录或存储,然后再重放。
store.dispatch({ type: 'counter/incremented' })
// {value: 1}
store.dispatch({ type: 'counter/incremented' })
// {value: 2}
store.dispatch({ type: 'counter/decremented' })
// {value: 1}

您无需直接更改状态,而是使用称为actions的普通对象指定要发生的更改。然后你编写一个称为reducer的特殊函数来决定每个动作如何转换整个应用程序的状态。

Redux 工具包示例

Redux Toolkit 简化了编写 Redux 逻辑和设置存储的过程。使用 Redux Toolkit,相同的逻辑如下所示:

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

const counterSlice = createSlice({
  name: 'counter',
  initialState: {
    value: 0
  },
  reducers: {
    incremented: state => {
      // Redux Toolkit 允许我们在 reducer 中编写“变异”逻辑。它
      // 没有实际上改变了状态,因为它使用了 Immer 库,
      // 它检测到“草稿状态”的变化并根据这些变化产生一个全新的
      // 不可变状态
      state.value += 1
    },
    decremented: state => {
      state.value -= 1
    }
  }
})

export const { incremented, decremented } = counterSlice.actions

const store = configureStore({
  reducer: counterSlice.reducer
})

// 仍然可以订阅商店
store.subscribe(() => console.log(store.getState()))

// 仍然将动作对象传递给 `dispatch`,但它们是为我们创建的
store.dispatch(incremented())
// {value: 1}
store.dispatch(incremented())
// {value: 2}
store.dispatch(decremented())
// {value: 1}

Redux Toolkit 允许我们编写更短且更易于阅读的逻辑,同时仍然遵循相同的 Redux 行为和数据流。

—END—

资源下载此资源为免费资源立即下载

申明:本文由第三方发布,内容仅代表作者观点,与本网站无关。对本文以及其中全部或者部分内容的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。本网发布或转载文章出于传递更多信息之目的,并不意味着赞同其观点或证实其描述,也不代表本网对其真实性负责。

七爪网 免费源码 Redux—JavaScript 应用程序的可预测状态容器 https://www.7claw.com/44985.html

分享免费的开源源码

常见问题
  • 1、自动:拍下后,点击(下载)链接即可下载;2、手动:拍下后,联系卖家发放即可或者联系官方找开发者发货。
查看详情
  • 1、源码默认交易周期:手动发货商品为1-3天,并且用户付款金额将会进入平台担保直到交易完成或者3-7天即可发放,如遇纠纷无限期延长收款金额直至纠纷解决或者退款!;
查看详情
  • 1、七爪会对双方交易的过程及交易商品的快照进行永久存档,以确保交易的真实、有效、安全! 2、七爪无法对如“永久包更新”、“永久技术支持”等类似交易之后的商家承诺做担保,请买家自行鉴别; 3、在源码同时有网站演示与图片演示,且站演与图演不一致时,默认按图演作为纠纷评判依据(特别声明或有商定除外); 4、在没有”无任何正当退款依据”的前提下,商品写有”一旦售出,概不支持退款”等类似的声明,视为无效声明; 5、在未拍下前,双方在QQ上所商定的交易内容,亦可成为纠纷评判依据(商定与描述冲突时,商定为准); 6、因聊天记录可作为纠纷评判依据,故双方联系时,只与对方在七爪上所留的QQ、手机号沟通,以防对方不承认自我承诺。 7、虽然交易产生纠纷的几率很小,但一定要保留如聊天记录、手机短信等这样的重要信息,以防产生纠纷时便于七爪介入快速处理。
查看详情
  • 1、七爪作为第三方中介平台,依据交易合同(商品描述、交易前商定的内容)来保障交易的安全及买卖双方的权益; 2、非平台线上交易的项目,出现任何后果均与互站无关;无论卖家以何理由要求线下交易的,请联系管理举报。
查看详情

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务