资讯专栏INFORMATION COLUMN

【全栈React】第20天: Redux动作

SimonMa / 854人阅读

摘要:去营救有一种方法我们把我们的归约器分成多个归约器每个都只负责状态树的叶子。此外我们还学习了如何扩展以使用多个归约器和动作以及多个连接的组件。

本文转载自:众成翻译
译者:iOSDevLog
链接:http://www.zcfy.cc/article/3825
原文:https://www.fullstackreact.com/30-days-of-react/day-20/

使用Redux,我们来谈谈我们如何在我们的应用中实际修改Redux状态。

昨天, 我们经历了整合我们的反应应用与Redux的困难部分。从现在起, 我们将使用我们的Redux设置来定义函数。

现在, 我们的演示应用能显示当前时间。但目前还没有任何方法可以更新到新的时间。现在, 让我们修改这个。

触发更新

回想一下, 我们能在Redux中改变数据的唯一方法是通过一个动作创建者。昨天我们创建了一个Redux的store, 但我们还没有为我们的store创造一个更新的方法。

我们 想要 的是我们的用户通过点击按钮来更新时间的能力。为了添加此函数, 我们需要执行以下几个步骤:

创建一个 actionCreator 来 分发 我们store的动作

调用一个元素的 actionCreator "onClick"

处理归约器的动作

我们已经实现了第三个步骤, 所以我们还有两件事要做, 才能让这个函数像我们预期的那样工作。

昨天, 我们讨论了什么是动作, 但不是真正的为什么我们使用这个东西叫 actionCreators 或他们是什么。

作为复习, 动作是一个_必须_ 包含type 值简单的对象,。我们创建了一个types.js 文件, 它保存在动作类型常量上, 因此我们可以将这些值用作type 属性。

export const FETCH_NEW_TIME = "FETCH_NEW_TIME";

作为快速审阅, 我们的动作可以是具有type 键的任何对象值。我们可以与我们的行动一起发送数据 (通常, 我们将把额外的数据作为一个动作的 payload 有效载荷 来传递)。

{
  type: types.FETCH_NEW_TIME,
  payload: new Date().toString()
}

现在, 我们需要在我们的store_分发_。我们可以这样做的一个方法就是调用store.dispatch() 函数。

store.dispatch({
  type: types.FETCH_NEW_TIME,
  payload: new Date().toString()
})

然而, 这是相当糟糕的做法。我们将使用一个函数来返回一个动作, 而不是直接发送该动作, 该函数将 创建 该动作 (因此名称: actionCreator)。这为我们提供了一个更好的测试故事 (易于测试)、可重用性、文档化和逻辑封装。

让我们在一个名为redux/actionCreators.js的文件中创建我们的第一个actionCreator 。我们将导出全部责任是返回一个适当的动作的一个函数, 以分发我们的store。

import * as types from "./types";

export const fetchNewTime = () => ({
  type: types.FETCH_NEW_TIME,
  payload: new Date().toString(),
})

export const login = (user) => ({
  type: types.LOGIN,
  payload: user
})

export const logout = () => ({
  type: types.LOGOUT,
})

现在, 如果我们调用这个函数, 什么都不会发生 , 除了返回一个动作对象。我们怎样才能让这个动作在store里分发?

It gets called with the dispatch function, so here we can bind the function to call dispatch() on the store.回想一下, 我们昨天使用了 connect() 函数导出从react-redux?第一个参数称为mapStateToProps, 它将状态映射到一个属性对象。connect() 函数接受第二个参数, 这使得我们也可以将函数映射到属性。它被调用的dispatch() 函数, 所以在这里我们可以 绑定 函数以便在store调用dispatch()

让我们来看看这个动作。在我们的src/views/Home/Home.js 文件中, 让我们通过提供第二个函数来更新我们的连接, 以使用我们刚刚创建的 actionCreator。我们将调用mapDispatchToProps这个函数。

import { fetchNewTime } from "../../redux/actionCreators";
  // ...
const mapDispatchToProps = dispatch => ({
  updateTime: () => dispatch(fetchNewTime())
})
  // ...
export default connect(
  mapStateToProps,
  mapDispatchToProps,
)(Home);

现在, updateTime()函数将作为属性传递, 并将调用dispatch() 当我们开始行动。让我们更新我们的 组件, 以便用户可以按下一个按钮来更新时间。

const Home = (props) => {
  return (
    

Welcome home!

Current time: {props.currentTime}

); }

虽然这个例子并不令人兴奋, 但它确实展示了Redux的特点。想象一下, 如果按钮获取新的鸣叫或我们有一个socket驱动更新到我们的Redux store。这个基本示例演示了Redux的完整功能。

[](#multi-reducers)多归约器

现在, 我们我们的应用有一个单一的归约器。这是目前的工作, 因为我们只有少量的简单数据和 (想必) 只有一个人在这个应用工作。试想一下, 在我们的应用中为_每一片数据_开发一个巨大的开关语句。

Ahhhhhhhhhhhhhh...

Redux去营救!Redux有一种方法, 我们把我们的Redux归约器分成多个归约器, 每个都只负责状态树的叶子。

我们可以从 redux 使用combineReducers() 导出, 以组成一个对象的归约器函数。对于每个触发的动作, 将使用相应的动作调用每个函数。让我们来看看这个动作。

假设我们 (也许更现实一些) 想跟踪当前用户。让我们创建一个currentUser Redux模块..。您猜到了: src/redux/currentUser.js`:

touch src/redux/currentUser.js

我们将导出我们从currentTime 模块导出的相同的四个值...... 当然, 这一次是针对 currentUser 的。我们在这里添加了一个基本的结构来处理当前用户:

import * as types from "./types"

export const initialState = {
  user: {},
  loggedIn: false
}

export const reducer = (state = initialState, action) => {
  switch (action.type) {
    case types.LOGIN:
      return {
        ...state, user: action.payload, loggedIn: true};
    case types.LOGOUT:
      return {
        ...state, user: {}, loggedIn: false};
    default:
      return state;
  }
}

让我们更新我们的configureStore() 函数来考虑这些分支, 使用combineReducers 将两个分支分开

import { createStore, combineReducers } from "redux";

import { rootReducer, initialState } from "./reducers"
import { reducer, initialState as userInitialState } from "./currentUser"

export const configureStore = () => {
  const store = createStore(
    combineReducers({
      time: rootReducer,
      user: reducer
    }), // root reducer
    {
      time: initialState, 
      user: userInitialState
    }, // our initialState
  );

  return store;
}

export default configureStore;

现在, 我们可以创建login()logout() 动作创造者在我们的store发送动作。

export const login = (user) => ({
  type: types.LOGIN,
  payload: user
})
  // ...
export const logout = () => ({
  type: types.LOGOUT,
})

现在, 我们可以使用 actionCreators 像updateTime() 动作创造者一样调用loginlogout

哦!这是Redux代码的又一个沉重的一天。今天, 我们完成了数据更新和在全局Redux状态中存储数据之间的循环。此外, 我们还学习了如何扩展Redux以使用多个归约器和动作以及多个连接的组件。

但是, 我们还没有对站外数据进行异步调用。明天我们将进入如何使用中间件与Redux, 这将使我们能够处理从我们的应用中获取远程数据, 仍然使用Redux的能力来保存我们的数据。

今天的工作很好, 明天见!

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/84722.html

相关文章

  • 全栈ReactReact 30教程索引

    摘要:今天我们将讨论创建组件的最终方案,即无状态函数的纯组件。今天我们正在研究一种处理提出的复杂数据的方法,称为体系结构。第天部署介绍今天,我们将探讨部署我们的应用所涉及的不同部分,以便外界可以使用我们的应用。 本文转载自:众成翻译译者:iOSDevLog链接:http://www.zcfy.cc/article/3758原文:https://www.fullstackreact.com/3...

    appetizerio 评论0 收藏0
  • 全栈React19: 用Redux进行数据管理

    摘要:归约器函数负责返回应用当前全局状态的表示形式。当我们在存储上发送操作时将使用应用的当前状态和导致状态更新的操作来调用此归约器函数。回到我们的归约器我们可以检查的动作类型并采取适当的步骤创建下一个状态。我们将处理动作创造者中归约器的副作用。 本文转载自:众成翻译译者:iOSDevLog链接:http://www.zcfy.cc/article/3811原文:https://www.ful...

    glumes 评论0 收藏0
  • 全栈React21: Redux中间件

    摘要:本文转载自众成翻译译者链接原文今天,我们在方法中使用中间件来管理我们的代码中的复杂状态变化。中间件是一个很好的地方。我们中间件我们将实现一些中间件它将代表我们处理异步请求。中间件位于动作和归并器之间。让我们创建我们的第一个中间件。 本文转载自:众成翻译译者:iOSDevLog链接:http://www.zcfy.cc/article/3810原文:https://www.fullsta...

    Scott 评论0 收藏0
  • 全栈React18: Flux 简介

    摘要:在方法中处理数据有三不同的角色派发器储存视图层我们的组件的主要思想是有一个单一源储存他们只能通过触发更新。这些操作负责调用派发器可以订阅更改并相应地更新自己的数据。与不同不使用派发器而是使用纯函数来定义数据变异函数。 本文转载自:众成翻译译者:iOSDevLog链接:http://www.zcfy.cc/article/3812原文:https://www.fullstackreact...

    mtunique 评论0 收藏0
  • 全栈React23: 实现测试

    摘要:包包含由团队提供的测试实用程序。将在一个名为的目录中自动查找整个树中的测试文件是的带有下划线。让我们为时间轴组件创建第一个测试。其中之一是命令。现在我们已经编写了第一个测试并确认了我们的设置我们将在明天开始测试我们的时间轴组件。 本文转载自:众成翻译译者:iOSDevLog链接:http://www.zcfy.cc/article/3807原文:https://www.fullstac...

    airborne007 评论0 收藏0

发表评论

0条评论

SimonMa

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<