你如何混合 componentDidMount() 和 react-redux connect()?

Posted

技术标签:

【中文标题】你如何混合 componentDidMount() 和 react-redux connect()?【英文标题】:How do you mix componentDidMount() with react-redux connect()? 【发布时间】:2017-03-14 03:13:09 【问题描述】:

这似乎是一个简单的用例,但我无法弄清楚。我想显示通过 HTTP 从对远程 API 的请求中检索到的项目列表。我希望在请求发生时屏幕最初显示为空白,然后在可用时填充结果。

所以我想我会有两个组件:愚蠢的“项目列表”组件,以及一个包装“展示”组件,呃,它以某种方式启动远程请求,同时使用来自状态的空项目列表呈现愚蠢的组件。

我知道如何启动初始远程请求:使用componentDidMount()

我知道如何处理调度/连接:我想使用类似的东西:

const OuterWrapper = connect(
   mapStateToProps,
   mapDispatchToProps
) (ItemList)

但是我怎样才能让这些东西一起玩呢?使用connect() 似乎让事情变得遥不可及。我想异步启动 API 请求,然后以某种方式执行 `dispatch(updateItemList(items)) 来告诉世界有新项目要添加到状态中。

编辑:

我找到了react-lifecycle-component,但我不明白示例用法,前后都有。在更长的情况下,为什么getAllTehDatas 被引用了两次?为什么它在mapDispatchToProps 中显然没有key:value 对?如果componentDidMount() 调用它,为什么还需要它呢?如果该方法需要使用dispatch(),你会怎么做?

【问题讨论】:

您是否已经有一个获取此数据的 redux 操作? 【参考方案1】:

首先,关于您的编辑,该仓库中的组件旨在让您将函数作为道具传递给组件。只要运行React lifecycle methods,它们就会运行。这很有用。但是这些原因在该回购中进行了解释,与您的问题无关。

另外,你看到了这个:

const mapDispatchToProps =  getAllTehDatas ;

这是 ES6 简写符号。它只是意味着:

const mapDispatchToProps =  getAllTehDatas: getAllTehDatas ;

即属性名与变量名相同。因为这是一个很常见的操作,所以有人聪明地想出了这个速记。如果你不知道它可能会非常混乱。你应该阅读about es6。

向前。

有许多概念没有明确界定。哑组件。智能组件。容器组件。表示组件。连接的组件。纯功能组件。很多。

容器组件智能组件,而展示组件哑组件。

有时愚蠢的组件有点聪明。也许他们在鼠标悬停时有动画。他们甚至可以拥有状态。

纯函数式组件只是一个函数。所以没有方法也没有状态。这意味着只有道具。由于不能有状态或额外的逻辑,因此纯函数式组件始终是展示性的。

一个连接的组件是一个高阶组件。这只是一个将您的组件呈现为子组件的父组件。它还可以优化渲染。

演示组件应该只显示东西而不是做东西。如果在您单击或键入内容时完成,则应由父级处理,该父级可以将处理程序传递给演示组件。表示组件可以做一些事情,但这些事情不能影响它们之外的任何东西。

容器组件应该决定会发生什么。这就是逻辑被塞进的地方。它更像是一个 React 概念而不是 Redux 概念。

连接的组件是用connect 创建的。当它被调用时,我们传递了一些函数。 mapStateToPropsmapDispatchToProps

mapStateToProps 可以做任何事情来生成一些道具供您的组件使用。这意味着您的组件随后可以使用这些道具,而无需进一步处理数据。所有需要的处理都可以在mapStateToProps完成。

mapDispatchToProps 可以做任何需要做的事情来传递直接用作事件处理程序的函数。我们经常传递绑定的动作创建者,它们通常已经完成了处理程序需要做的所有事情。但是我们可以传递任何函数并给它起任何名字。所以我们可以称它为onClick 并传递我们喜欢的任何函数。您还可以在 Redux-Thunk 的帮助下创建复杂的动作创建者,将任何事件处理程序变成智能动作创建者。 Thunked 动作创建者可以访问调度和状态。

以上2段勾勒了一个有趣的点:connect在我们mapStateToPropsmapDispatchToProps的帮助下创建的HOC可以很容易地做成一个完整的智能组件,并且包裹的组件可以完全呈现​​,即使由此产生的 HOC 是做聪明的事情。

或者得到这个:你可以connect一个已经连接的组件。肯定是令人兴奋的。这样做有用吗?当然可以。一个组件可能需要一些来自状态的通用数据,无论它在哪里使用。你connect它到那个数据。然后,生成的组件可以connected 到特定于它在其他地方使用的地方的数据。常见的?不,有用吗?是的!

您还可以将展示组件包装在容器组件中,然后用connect 包装。这可能是您正在寻找的。然后您可以使用componentDidMount 在容器组件中进行提取。

但表现性组件与它们的智能区分开来只有两个原因:

可重用性 可测试性

如果两者都不需要,则不应将两者分开。为什么要把事情复杂化却没有收获?

另外,使用componentDidMount,而不是componentWillMount。如果您使用通用组件,后者也在服务器端运行。您不希望您的 fetch 在服务器上运行。

请注意,即使连接的组件显然是一个包装器,您也不应该那样想它。将其视为原始版本的插件版本。包装只是一个实现细节。此外,包装器是由 React-Redux 创建和维护的,它的内部不能乱七八糟。这意味着您不能更改包装器的 componentDidMount 或任何其他部分。当我说你不能时,我的意思是你完全可以但真的不应该。

回顾一下,我建议了解 React、Redux 和 React-Redux。他们相处得很好,但不是一回事。

在你掌握了概念之后,你就去做你认为最好的事情。制定自己的规则。

【讨论】:

“这意味着您不能更改包装器的 componentDidMount 或任何其他部分。”你所说的“改变”是什么意思?我必须在某处写一个componentDidMount... 我意识到我让事情变得过于复杂......一旦开始编码,我意识到我什至不必将项目列表包装在更新程序组件中。我只是把它做成一个带有空渲染的单独组件,一旦它检索到数据就会发送适当的操作。对我来说棘手的部分是调度的使用,但我意识到如果你从上面传递一个 lambda 就很好了。【参考方案2】:

This answer我前段时间给你一个例子,告诉你如何正确使用connect并在组件中进行action调用。唯一的区别是它在我的 componentWillMount 中:P

【讨论】:

componentWillMount 也可以在通用组件的服务器上运行。通过把你的引导代码放在那里,它不能在通用的 React 应用程序中使用。您现在可能不在乎,但以后可能会。此外,这可能不是对其他人的最佳建议。 我没有使用引导程序。我所有的应用程序都是纯反应原生的。我有状态呈现好东西,具体取决于 api 调用是否完成(如未完成时的微调器) Bootstrapping 是开发人员的术语,意思是启动。就像启动计算机一样。它来自“靠自己的力量让自己振作起来”一词,指的是几乎从零开始。 Bootstrap 库就是以此命名的,但我指的不是那个库。 所以基本上,如果我需要一个连接的组件并且在生命周期方法中发生一些事情(即componentDidMount 中的 api 调用),那么我必须实现 componentWillReceiveProps 以跟上Redux 不断地传递 props。

以上是关于你如何混合 componentDidMount() 和 react-redux connect()?的主要内容,如果未能解决你的问题,请参考以下文章

如何动态调用componentDidMount中的函数?

ReactJs:如何在渲染之前等待 componentDidMount() 完成?

如何更新 componentDidMount 中的上下文状态?

如何让 componentDidMount 再次渲染?

react请求接口数据是在componentDidMount 还是componentWillMount周期好

axios在componentDidMount中获取数据后如何拍摄jest snapshot?