了解 Redux 的基本实现 | prevState 是如何使用的?
Understanding a basic implementation of Redux | how is prevState used?
我正在查看 this article 中 redux 的超级基本实现示例。除了 dispatch 使用 prevState
的地方,我理解它。首先这个函数从哪里获得prevState?这与计数器需要的实际状态有什么关系?它是否在名为 prevState 的状态中隐式设置了另一个值?我只是很难理解状态实际上是如何传递给调度然后通过 prevState 反击的。我认为这可能是我还没有掌握的函数式编程思想。感谢您帮助我理解!
import React, { Component } from 'react';
const counter = (state = { value: 0 }, action) => {
switch (action.type) {
case 'INCREMENT':
return { value: state.value + 1 };
case 'DECREMENT':
return { value: state.value - 1 };
default:
return state;
}
}
class Counter extends Component {
state = counter(undefined, {});
dispatch(action) {
this.setState(prevState => counter(prevState, action));
}
increment = () => {
this.dispatch({ type: 'INCREMENT' });
};
decrement = () => {
this.dispatch({ type: 'DECREMENT' });
};
render() {
return (
<div>
{this.state.value}
<button onClick={this.increment}>+</button>
<button onClick={this.decrement}>-</button>
</div>
)
}
}
prevState
在这种情况下是实际的当前状态。它不是时光倒流,它只是 returns 你当前的状态,它将被用来构建一个新的状态——因为在 Redux 和 React 的概念中,状态是 immutable
,这意味着它永远不会被修改——当你发送新的动作并用你的减速器处理它时——你正在创建全新的对象(状态)。
React.Component.prototype.setState
React 的 setState
方法在这里负责 prevState
– 不是 redux,只是为了清楚。
让我们看看如何使用setState
。我们有 3 个选项 ...
setState(nextState)
- 只需传递下一个状态,React 就会相应地更新组件 state
setState(nextState, callback)
– 可选地指定一个回调,一旦组件被重新渲染就会调用 – React 组件将在 state
更新时重新渲染 – 注意:React 文档通常建议使用componentDidUpdate
生命周期方法。
setState((prevState, props) => nextState)
– 调用一个方便绑定 prevState
和 props
标识符的函数,以便我们手动更新我们的状态。预计我们提供的功能 return 是下一个状态
所以你有这个
this.setState(prevState => counter(prevState, action));
如果不是很明显,您提供的代码示例使用的是 #3。因此,第一个参数 prevState
将由 React 提供,即组件的 current 状态。第二个参数 props
没有在这里使用,所以我们将忽略它(一般的想法是你可以使用道具来更新你的状态)。
什么是prevState
?
prevState
到底是什么?好吧,我们确定它是您组件的当前状态,我们之前在 Counter 中将其初始化为
state = counter(undefined, {});
// => { value: 0 }
所以当我们派发一个 INCREMENT
时,我们会得到类似
的东西
this.setState(prevState => counter({value: 0}, {type: 'INCREMENT'})
在这种情况下 counter
(减速器)将 return
{value: 1}
这个 return 值是组件下一个 状态
重复申请setState
当然,如果我们再次INCREMENT
,我们会得到类似
的东西
this.setState(prevState => counter({value: 1}, {type: 'INCREMENT'})
其中 counter
会 return
{value: 2}
成为组件的下一个状态
等等..
"Where is line between React and Redux?"
首先,特定于 React 的代码是 import
和扩展 Component
.
的 Counter
class
"But what is the other code (counter
) then?"
关于 redux 的最酷的事情之一是它的 无状态 – Redux 仅作为模式存在于此代码示例中。没有使用 redux
或 react-redux
的 import
。 Redux 在这里更多地用作 redux idea/philosophy 的实现——它是围绕单向数据流和可组合的 reducer 的思想构建的。
"What is a reducer?"
reducer 只是一个函数,当应用于状态和动作时,returns 一个 new 状态。
当然,redux
库包含一些有用的实用程序,可以更轻松地在您的应用程序中实现 Redux 的模式——但实际上,它们都是非常简单的功能。事实上,Redux 的创建者 Dan Abramov 有一个关于 egghead 的 awesome(免费)系列,Getting Started with Redux 向您展示了 Redux 是如何工作的,一个接一个。在我看来,它是有史以来最好的编码视频系列之一,涉及 任何 主题。
首先,请注意 Class Counter 扩展自 React 的 Component 类型。正因为如此它会继承一堆属性和方法,其中之一就是setState.
我们从React documentation for setState可以看出它有两个参数:
setState(nextState, callback)
但细则中是这样写的:"The first argument can be an object (containing zero or more keys to update) or a function (of state and props) that returns an object containing keys to update."
在这里的例子中,我们只传递一个参数,所以我们必须使用它,第一个参数是一个函数,returns 一个要更新的键对象。
如果我们再看一下使用 setState 的原始代码:
this.setState(prevState => counter(prevState, action));
如果我们用 es5 JavaScript 语法写这个可能会更容易阅读和理解:
this.setState(
function cb(prevstate) {
return counter(prevstate, action)
})
所以在这种情况下 "prevState" 是匿名函数的参数。理论上,它可以被命名为任何东西,只要你在函数体内使用相同的名字来引用它,一切都会好起来的。然而,将它命名为 "prevState" 似乎是一个非常标准的事情(这是 React 文档使用的)。
如果我们将其视为纯粹的 JavaScript,则您传递给此函数的 prevState 应该是未定义的。
因此,多次触发 INCREMENT 操作应该会导致您的状态值始终为 1,因为计数器函数将始终使用默认值:
state = { value: 0 }
我认为调度函数应该是这样的:
dispatch(action) {
this.setState(counter(this.state, action));
}
更新
This link 可能会更好地解释它,但实际上如果你使用一个函数作为 setState 的第一个参数,那么 这个函数将把当前状态作为它的参数,这就是 prevState 获取其值的方式。
我正在查看 this article 中 redux 的超级基本实现示例。除了 dispatch 使用 prevState
的地方,我理解它。首先这个函数从哪里获得prevState?这与计数器需要的实际状态有什么关系?它是否在名为 prevState 的状态中隐式设置了另一个值?我只是很难理解状态实际上是如何传递给调度然后通过 prevState 反击的。我认为这可能是我还没有掌握的函数式编程思想。感谢您帮助我理解!
import React, { Component } from 'react';
const counter = (state = { value: 0 }, action) => {
switch (action.type) {
case 'INCREMENT':
return { value: state.value + 1 };
case 'DECREMENT':
return { value: state.value - 1 };
default:
return state;
}
}
class Counter extends Component {
state = counter(undefined, {});
dispatch(action) {
this.setState(prevState => counter(prevState, action));
}
increment = () => {
this.dispatch({ type: 'INCREMENT' });
};
decrement = () => {
this.dispatch({ type: 'DECREMENT' });
};
render() {
return (
<div>
{this.state.value}
<button onClick={this.increment}>+</button>
<button onClick={this.decrement}>-</button>
</div>
)
}
}
prevState
在这种情况下是实际的当前状态。它不是时光倒流,它只是 returns 你当前的状态,它将被用来构建一个新的状态——因为在 Redux 和 React 的概念中,状态是 immutable
,这意味着它永远不会被修改——当你发送新的动作并用你的减速器处理它时——你正在创建全新的对象(状态)。
React.Component.prototype.setState
React 的 setState
方法在这里负责 prevState
– 不是 redux,只是为了清楚。
让我们看看如何使用setState
。我们有 3 个选项 ...
setState(nextState)
- 只需传递下一个状态,React 就会相应地更新组件state
setState(nextState, callback)
– 可选地指定一个回调,一旦组件被重新渲染就会调用 – React 组件将在state
更新时重新渲染 – 注意:React 文档通常建议使用componentDidUpdate
生命周期方法。setState((prevState, props) => nextState)
– 调用一个方便绑定prevState
和props
标识符的函数,以便我们手动更新我们的状态。预计我们提供的功能 return 是下一个状态
所以你有这个
this.setState(prevState => counter(prevState, action));
如果不是很明显,您提供的代码示例使用的是 #3。因此,第一个参数 prevState
将由 React 提供,即组件的 current 状态。第二个参数 props
没有在这里使用,所以我们将忽略它(一般的想法是你可以使用道具来更新你的状态)。
什么是prevState
?
prevState
到底是什么?好吧,我们确定它是您组件的当前状态,我们之前在 Counter 中将其初始化为
state = counter(undefined, {});
// => { value: 0 }
所以当我们派发一个 INCREMENT
时,我们会得到类似
this.setState(prevState => counter({value: 0}, {type: 'INCREMENT'})
在这种情况下 counter
(减速器)将 return
{value: 1}
这个 return 值是组件下一个 状态
重复申请setState
当然,如果我们再次INCREMENT
,我们会得到类似
this.setState(prevState => counter({value: 1}, {type: 'INCREMENT'})
其中 counter
会 return
{value: 2}
成为组件的下一个状态
等等..
"Where is line between React and Redux?"
首先,特定于 React 的代码是 import
和扩展 Component
.
Counter
class
"But what is the other code (counter
) then?"
关于 redux 的最酷的事情之一是它的 无状态 – Redux 仅作为模式存在于此代码示例中。没有使用 redux
或 react-redux
的 import
。 Redux 在这里更多地用作 redux idea/philosophy 的实现——它是围绕单向数据流和可组合的 reducer 的思想构建的。
"What is a reducer?"
reducer 只是一个函数,当应用于状态和动作时,returns 一个 new 状态。
当然,redux
库包含一些有用的实用程序,可以更轻松地在您的应用程序中实现 Redux 的模式——但实际上,它们都是非常简单的功能。事实上,Redux 的创建者 Dan Abramov 有一个关于 egghead 的 awesome(免费)系列,Getting Started with Redux 向您展示了 Redux 是如何工作的,一个接一个。在我看来,它是有史以来最好的编码视频系列之一,涉及 任何 主题。
首先,请注意 Class Counter 扩展自 React 的 Component 类型。正因为如此它会继承一堆属性和方法,其中之一就是setState.
我们从React documentation for setState可以看出它有两个参数:
setState(nextState, callback)
但细则中是这样写的:"The first argument can be an object (containing zero or more keys to update) or a function (of state and props) that returns an object containing keys to update."
在这里的例子中,我们只传递一个参数,所以我们必须使用它,第一个参数是一个函数,returns 一个要更新的键对象。
如果我们再看一下使用 setState 的原始代码:
this.setState(prevState => counter(prevState, action));
如果我们用 es5 JavaScript 语法写这个可能会更容易阅读和理解:
this.setState(
function cb(prevstate) {
return counter(prevstate, action)
})
所以在这种情况下 "prevState" 是匿名函数的参数。理论上,它可以被命名为任何东西,只要你在函数体内使用相同的名字来引用它,一切都会好起来的。然而,将它命名为 "prevState" 似乎是一个非常标准的事情(这是 React 文档使用的)。
如果我们将其视为纯粹的 JavaScript,则您传递给此函数的 prevState 应该是未定义的。
因此,多次触发 INCREMENT 操作应该会导致您的状态值始终为 1,因为计数器函数将始终使用默认值:
state = { value: 0 }
我认为调度函数应该是这样的:
dispatch(action) {
this.setState(counter(this.state, action));
}
更新
This link 可能会更好地解释它,但实际上如果你使用一个函数作为 setState 的第一个参数,那么 这个函数将把当前状态作为它的参数,这就是 prevState 获取其值的方式。