应对redux基础

For my final Flatiron portfolio project, I had to write a React app that made use of Redux middleware to respond to and modify state changes. I had just mastered React and passing down props and adding a local state to a class component made sense to me, so I wasn’t sure why we had to complicate things with Redux.

对于我的最后Flatiron投资项目,我必须编写一个React应用,该应用使用Redux中间件来响应和修改状态更改。 我刚刚掌握了React并传递了道具并在类组件中添加了本地状态对我来说很有意义,所以我不确定为什么我们必须使Redux变得复杂。

At first I had trouble grasping the point of Redux besides adding what seemed like a billion new steps to complete a simple state change.

起初,除了添加似乎十亿美元的新步骤来完成简单的状态更改之外,我很难理解Redux的要点。

On top of that, all the steps came with a bunch of new confusing terminology. My brain, not exactly in peak condition busy as it was constantly re-learning how life is supposed to work in 2020, just about broke waiting for everything to fall into place.

最重要的是,所有步骤都带有一堆新的令人困惑的术语。 我的大脑并没有完全处于高峰状态,因为它一直在重新学习2020年应该如何生活,但几乎一切都停滞不前,一切都准备就绪。

Action creator, don’t leave the house, store, stop touching your face, mapDispatchToProps…was that teargas???
动作创造者,不要离开屋子,存放东西,别碰你的脸,mapDispatchToProps…是催泪瓦斯吗???

Now that I’m (am I?) on the other side of that, I thought I’d break down a few of the fundamental concepts in case it helps someone else avoid what I’m calling the Redux Brain Break.

既然我(我是?)的另一面,我想我会分解一些基本概念,以防它有助于其他人避免所谓的Redux Brain Break。

州/店 (State/Store)

I’m going to start with state, since this is not an entirely new concept if you’re familiar with React. The state is where we can stash useful information to use later on. It looks like a plain old JavaScript object (POJO) with key/value pairs. The values can be strings, arrays, objects, anything that is expected to change at some point during the component’s life. One key difference between props and state is props are used for properties that are passed down from a parent component, so they can’t be easily changed. State is typically for storing data that needs to change at some point throughout the component’s life.

我将从状态开始,因为如果您熟悉React,这不是一个全新的概念。 状态是我们可以存储有用信息的地方,以便以后使用。 它看起来像一个带有键/值对的普通旧式JavaScript对象(PO​​JO)。 这些值可以是字符串,数组,对象,也可以是在组件生命周期中某些时候可能发生变化的任何值。 propsstate之间的一个关键区别是,道具用于从父组件传递下来的属性,因此不能轻易更改它们。 状态通常用于存储在组件生命周期中某个时刻需要更改的数据

state = {
locations: [{...}],
formData: {...},
currentUser: "Lisa Simpson"}

States can be local to Components (meaning scoped to be used anywhere within a class component), but using Redux it can be stored in a globally accessible state. In fact, the whole purpose of Redux is to manage this state store. In order to access it, a component needs to connect to that store, it’s not accessible by default. Still with me?

状态可以是组件的局部状态 (意味着范围可以在类组件内的任何地方使用),但是使用Redux可以将其存储为全局可访问状态。 实际上, Redux的全部目的是管理该状态存储。 为了访问它,组件需要连接到该商店,默认情况下是不可访问的。 还在我这儿?

Let’s say we’re fetching data from an external API and storing that data in the Redux store because we may be adding or changing that data. For example, in my app I’m fetching location data, and people can add locations and send them back to the API to be saved in a database.

假设我们正在从外部API提取数据并将该数据存储在Redux存储中,因为我们可能会添加或更改该数据。 例如,在我的应用程序中,我正在获取位置数据,人们可以添加位置并将其发送回API,以保存在数据库中。

There are components that aren’t going to need to use this location data and don’t need to re-render every time it changes. That’s why they’re not automatically connected to the store, it helps with performance. But what if a component does need to access that data?

有些组件不需要使用此位置数据,也不需要在每次更改时都重新渲染。 这就是为什么他们不会自动连接到商店,这有助于提高性能 。 但是,如果某个组件确实需要访问该数据怎么办?

mapStateToProps() (mapStateToProps())

That is where mapStateToProps() comes in. Connect the component to the Redux store and use mapStateToProps() to indicate which parts of the state its going to use, which will bring that data from the store into your component’s props. mapStateToProps() is a function that takes in the store’sstate as an argument and returns an object with the new props to give to the component. These new props are given as an argument when using the connect method to connect to the Redux store. Eg.

这就是mapStateToProps()进入的地方。将组件连接到Redux商店,并使用mapStateToProps()指示其要使用的状态的哪一部分,这会将来自商店的数据带入组件的道具中。 mapStateToProps()是一个函数,该函数将商店的state作为参数,并返回带有新道具的对象以提供给组件。 这些新道具在使用connect方法连接到Redux存储时作为参数给出。 例如。

const mapStateToProps = state => {
return {
formData: state.locationForm
}
}export default connect(mapStateToProps)(NameOfComponent);

Mapping the formData to a component’s props allows that component (in this case a form to add or edit a location) to pull from and update that formData. this.props.formData would now return an object that might look like:

将formData映射到组件的props可使该组件(在本例中为添加或编辑位置的表单)从该formData中提取和更新。 this.props.formData现在将返回一个可能类似于以下内容的对象:

{
name: "Apple tree",
address: "2821 Telegraph Ave, Berkeley, CA 94705",
lat: 37.8588635,
lng: -122.2591357
}

But what if we‘re loading a fresh form to add a new location and we want to reset the formData so it doesn’t display anything until a user types new information into the form? Or someone needs to edit that data? We can’t do something like create a function that returns this.setState({new form data goes here}) to update the state. No…that would be too easy for Redux.

但是,如果我们正在加载一个新表单以添加新位置并且想要重置formData以便在用户向表单中输入新信息之前不显示任何内容,该怎么办? 还是有人需要编辑该数据? 我们无法做类似创建返回this.setState({new form data goes here})的函数来更新状态的操作。 不……对于Redux 来说太容易了。

分解Redux流程 (Breaking Down The Redux Flow)

Remember the Rube Goldberg-like series of events I alluded to earlier? Well, here’s where that really kicks in. To update the store’sstate a very specific series of events must take place. It doesn’t really feel like a linear path, though, at least not in my brain (which happens to be very prone to tangents). This is what that path looks like to me:

还记得我之前提到的类似鲁伯·戈德堡的系列活动吗? 好吧,这就是真正要去的地方。要更新商店的state ,必须发生一系列非常特定的事件。 但是,它并不是真正的线性路径,至少在我的大脑中不是(这很容易产生切线)。 这就是我的那条路:

  1. Something happens on the client’s side to trigger a change in state. This might be something like clicking on a button or typing in a form field. We’ll call this an event.

    客户端方面发生了一些事情,以触发状态更改。 这可能类似于单击按钮或在表单字段中键入。 我们将其称为事件

  2. The event handler (the function in your component that determines what is to be done when someone triggers an event) specifies what part of the state should be updated using the store’s dispatch() method. The dispatch method takes in an argument with some information about how the state should be updated. Within the event handler that might (but probably doesn’t, see mapDispatchToProps below) look like:this.props.store.dispatch(action).

    事件处理程序(组件中的函数,当某人触发事件时确定要执行的操作)指定应使用商店的dispatch()方法更新状态的哪一部分。 dispatch方法接受一个参数,其中包含有关应如何更新状态的一些信息。 在事件处理程序中,可能(但可能没有,请参见下面的mapDispatchToProps)看起来像: this.props.store.dispatch(action)

    The dispatch function doesn’t really return anything*, it’s there tell the store to fire off (aka dispatch) a state change as well as what type of change.

    调度功能实际上并不会返回任何*,它会告诉商店触发(也称为调度)状态更改以及哪种类型的更改。

  3. But what’s that argument passed into the dispatch method? That’s called an action. An action is a POJO with a ‘type’ key.

    但是该参数传递给dispatch方法的是什么? 这就是所谓的动作 。 动作是带有“类型”键的POJO。

    Eg.

    例如。

    { type: 'RESET_FORM' }. Actions can also have keys with additional information, often called their payload, eg. { type: 'UPDATE_FORM', formData: {...} }. Yes, that stationary POJO is called an action. Why? I don’t know. I guess it has something to do with how it tells the reducer what action to take.

    { type: 'RESET_FORM' } 。 动作也可以具有带有附加信息的键,例如,通常称为其有效负载。 { type: 'UPDATE_FORM', formData: {...} } 。 是的,该静态POJO称为动作。 为什么? 我不知道。 我猜这与它告诉减速器采取什么措施有关。

  4. Oh cool! Another word with no obvious meaning! Despite the name, the reducer is where most of the action happens. Back when we created the store (this happens at the very top of our app, often in index.js), it is passed a reducer (or a set of reducers) as an argument. A reducer is a pure function that takes in the previous state and an action as arguments, and returns a copy of the state, now updated. It looks like: reducerName(initialState, action) => updatedState. The reducer is what actually returns our updated state!

    太酷了! 另一个没有明显含义的词! 尽管有名称,但减速器是大多数动作发生的地方。 回到创建商店时(这种情况通常发生在应用程序的顶部,通常在index.js中),将其传递给reducer(或一组reducer)作为参数。 精简器是一个纯函数,它以先前的状态和一个动作作为参数,并返回状态的副本,此状态现已更新。 它看起来像: reducerName(initialState, action) => updatedState 。 减速器实际上返回了我们的更新状态!

So, eventHandler(event) => dispatch(action) => reducer(initialState, action) => Updated State!

因此,eventHandler(event)=> dispatch(action)=> reducer(initialState,action)=>更新状态!

更多关于减速器 (More on Reducers)

I said above that dispatch tells the store what action to take. I also said it triggers this action. Well, it triggers the action by passing the action object as an argument along with the current state to the reducer. If it is keeping track of more than one reducer the state and action are passed to all of them until a reducer with a switch case for the action’s type is found and a new state is returned based on what the reducer tells it to return. In the case that the action.type ==='RESET_FORM', for instance, it might return a copy of the state with blank form fields. I mention a “copy” of the state, because reducers are pure functions. This means there are no side effects and we can’t change the original state, so we return a modified copy of it.

我在上面说过,调度告诉商店要采取什么行动。 我还说过,它将触发此动作。 好吧,它通过将操作对象作为参数与当前状态一起传递给reducer来触发操作。 如果跟踪多个减速器,则将状态和动作传递给所有减速器,直到找到具有针对动作类型的开关盒的减速器,并根据减速器指示其返回的状态返回新状态。 例如,在action.type ==='RESET_FORM',的情况下,它可能会返回带有空白表单字段的状态副本。 我提到状态的“副本”,因为化简器是纯函数。 这意味着没有副作用,并且我们不能更改原始状态,因此我们返回其修改后的副本。

What you name your reducer determines the key for the updated part of the state we’re working on, (which if you remember was determined by the action). If the reducer is called locationForm.js, then it will return a copy of the state which includes locationForm and its data as a key/value pair. If the initial state included another key, perhaps from another reducer, it will include that as well. For example:

减速器的名称确定了我们正在处理的状态的更新部分的密钥(如果您还记得,它是由操作确定的)。 如果reducer称为locationForm.js,则它将返回状态的副本,其中包括locationForm及其数据作为键/值对。 如果初始状态包括另一个密钥(可能来自另一个还原器),则它将也包括该密钥。 例如:

state = {
locationForm: {
name: "a name",
address: "123 Sesame St., Berkeley, CA",
etc.
}
locations: [{...}, {...}, {...}]
}

mapDispatchToProps() (mapDispatchToProps())

When you connect your component to the store, I mentioned above you will pass in mapStateToProps (the function) as an argument. If you’re updating the state in this component, you’ll also want to pass in either a mapDispatchToProps() function, or an object. Then the component will have access to the dispatch method as dispatch() rather than this.props.store.dispatch() and you can dispatch your action from the event handler.

当您将组件连接到商店时,如上所述,您将传入mapStateToProps(该函数)作为参数。 如果要更新此组件中的状态,则还需要传递mapDispatchToProps()函数或对象。 然后,该组件将可以使用dispatch()而不是this.props.store.dispatch()的方式访问dispatch方法,并且您可以从事件处理程序中调度动作。

Image for post
code at the bottom of a LocationForm component. mapDispatchToProps is passing in an action creator to dispatch, the return value of which is an action object
在LocationForm组件底部的代码。 mapDispatchToProps传入动作创建者进行分派,其返回值是一个动作对象

*Dispatch CAN return a promise (when asynchronously fetching data, for instance) when paired with middleware like Redux Thunk.

*与Redux Thunk等中间件配对时,Dispatch可以返回承诺(例如,异步获取数据时)。

翻译自: https://medium.com/swlh/react-redux-fundamentals-7438b4638e57

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值