Redux 会自动更新它连接的 React 组件吗?
Does Redux update the React component it is connected to automatically?
我的印象是当我的 Redux store 更新时(通过向 reducer 发送一个动作),我的 Provider 应该让新的 store 可用于它的所有 child 组件。因此,当我使用 mapStateToProps() 将容器组件连接到商店时,该组件在收到与商店一起更新的新道具时应该 re-render,而不需要 componentWillReceiveProps()。我这样想错了吗?
在阅读了几个小时的文档和其他堆栈溢出答案之后,我发现有些东西不合我意。我很确定我的 reducer 工作正常并且正在返回一个新的 object,我的组件可以访问商店,并且我的初始状态渲染得很好。如果有人能让我更好地了解事物的流程,我将永远感激不已。
基本上,我有一个 header 组件导入商店,使用 Provider 并呈现一个 "FAQ" 组件:
import React from 'react';
import FAQ from './Faq';
import {Provider} from "react-redux";
import store from '../store/index'
class Header extends React.Component {
render() {
return (
<Provider store = {store}>
<FAQ />
</Provider>
)
}
}
export default Header;
"FAQ" 组件是一个容器,通过 mapStateToProps() 连接到商店,它导入 "FAQTest" 组件,这是一个将被传递的展示组件 this.state.thisFood作为道具,以便它可以呈现商店中的数据。还有一个 "addFood" 调度我的动作的函数,可以在底部的 mapDispatchToProps() 中看到。
import React from 'react';
import {connect} from 'react-redux';
import FAQTest from './faqTest';
class FAQ extends React.Component {
constructor(props) {
super(props);
this.state = {
thisFood: props.breakfast
};
}
//adding this makes the component state update, but I think it should work without it
componentWillReceiveProps(nextProps){
this.setState({thisFood: nextProps.breakfast})
}
addFood = () => {
this.props.addFood();
}
render() {
return (
<React.Fragment>
<button onClick={this.addFood}> Add Food </button>
<FAQTest food = {this.state.thisFood} />
</React.Fragment>
)
}
}
const mapStateToProps = function(state) {
return {
breakfast: state.faq.breakfast
}
}
function mapDispatchToProps(dispatch) {
return {
addFood: () => dispatch({type: 'ADD_FOOD', food: 'Waffles'})
}
}
export default connect(mapStateToProps, mapDispatchToProps)(FAQ);
当我单击 "Add Food" 按钮时,由于 mapStateToProps(),我的商店得到更新,我的 FAQ 容器组件的道具也得到更新。我认为这会触发我的 FAQ 组件更新其状态,但是除非我使用 componentWillReceiveProps,否则状态不会更新。这是否按预期工作?
以防万一我做了一些傻事,这是我的减速器:
const initialState = {
breakfast: ["eggs", "bacon"]
}
export default function faqReducer(state = initialState, action) {
switch (action.type) {
case "ADD_FOOD":
return Object.assign({}, state, {
breakfast: [...state.breakfast, action.food]
})
default:
return state;
}
}
这是我的根减速器和我的 combineReducers() 函数:
import { combineReducers } from "redux";
import faq from './faqReducer'
export default combineReducers({
faq: faq
});
问题是您正在将数据从 props 复制到状态,但仅在安装组件时才这样做,然后期望状态在新的 props 到达时以某种方式更新。
Copying data from props to state is almost always the wrong approach。请不要那样做。只需使用道具的价值。
另外两条改进代码的建议:
- 更喜欢使用 the "object shorthand" form of
mapDispatch
,而不是将其编写为函数
- 我们建议使用我们新的官方 Redux Starter Kit package 作为编写 Redux 逻辑的标准方式。它包括用于简化几个常见 Redux 用例的实用程序,包括存储设置、定义缩减器、不可变更新逻辑,甚至一次创建整个 "slices" 状态。
我的印象是当我的 Redux store 更新时(通过向 reducer 发送一个动作),我的 Provider 应该让新的 store 可用于它的所有 child 组件。因此,当我使用 mapStateToProps() 将容器组件连接到商店时,该组件在收到与商店一起更新的新道具时应该 re-render,而不需要 componentWillReceiveProps()。我这样想错了吗?
在阅读了几个小时的文档和其他堆栈溢出答案之后,我发现有些东西不合我意。我很确定我的 reducer 工作正常并且正在返回一个新的 object,我的组件可以访问商店,并且我的初始状态渲染得很好。如果有人能让我更好地了解事物的流程,我将永远感激不已。
基本上,我有一个 header 组件导入商店,使用 Provider 并呈现一个 "FAQ" 组件:
import React from 'react';
import FAQ from './Faq';
import {Provider} from "react-redux";
import store from '../store/index'
class Header extends React.Component {
render() {
return (
<Provider store = {store}>
<FAQ />
</Provider>
)
}
}
export default Header;
"FAQ" 组件是一个容器,通过 mapStateToProps() 连接到商店,它导入 "FAQTest" 组件,这是一个将被传递的展示组件 this.state.thisFood作为道具,以便它可以呈现商店中的数据。还有一个 "addFood" 调度我的动作的函数,可以在底部的 mapDispatchToProps() 中看到。
import React from 'react';
import {connect} from 'react-redux';
import FAQTest from './faqTest';
class FAQ extends React.Component {
constructor(props) {
super(props);
this.state = {
thisFood: props.breakfast
};
}
//adding this makes the component state update, but I think it should work without it
componentWillReceiveProps(nextProps){
this.setState({thisFood: nextProps.breakfast})
}
addFood = () => {
this.props.addFood();
}
render() {
return (
<React.Fragment>
<button onClick={this.addFood}> Add Food </button>
<FAQTest food = {this.state.thisFood} />
</React.Fragment>
)
}
}
const mapStateToProps = function(state) {
return {
breakfast: state.faq.breakfast
}
}
function mapDispatchToProps(dispatch) {
return {
addFood: () => dispatch({type: 'ADD_FOOD', food: 'Waffles'})
}
}
export default connect(mapStateToProps, mapDispatchToProps)(FAQ);
当我单击 "Add Food" 按钮时,由于 mapStateToProps(),我的商店得到更新,我的 FAQ 容器组件的道具也得到更新。我认为这会触发我的 FAQ 组件更新其状态,但是除非我使用 componentWillReceiveProps,否则状态不会更新。这是否按预期工作?
以防万一我做了一些傻事,这是我的减速器:
const initialState = {
breakfast: ["eggs", "bacon"]
}
export default function faqReducer(state = initialState, action) {
switch (action.type) {
case "ADD_FOOD":
return Object.assign({}, state, {
breakfast: [...state.breakfast, action.food]
})
default:
return state;
}
}
这是我的根减速器和我的 combineReducers() 函数:
import { combineReducers } from "redux";
import faq from './faqReducer'
export default combineReducers({
faq: faq
});
问题是您正在将数据从 props 复制到状态,但仅在安装组件时才这样做,然后期望状态在新的 props 到达时以某种方式更新。
Copying data from props to state is almost always the wrong approach。请不要那样做。只需使用道具的价值。
另外两条改进代码的建议:
- 更喜欢使用 the "object shorthand" form of
mapDispatch
,而不是将其编写为函数 - 我们建议使用我们新的官方 Redux Starter Kit package 作为编写 Redux 逻辑的标准方式。它包括用于简化几个常见 Redux 用例的实用程序,包括存储设置、定义缩减器、不可变更新逻辑,甚至一次创建整个 "slices" 状态。