ReactJS:为什么将组件的初始状态传递为prop是反模式?


78

我已经在SocketIO的帮助下创建了一个小的ReactJS仪表板,用于实时更新。即使我更新了仪表板,也使我感到不确定我是否正确执行了操作。

最让我感到困扰的是getInitialState中Props作为反模式发布。我创建了一个仪表板,该仪表板从服务器获取实时更新,除了加载页面外,不需要用户交互。根据我的阅读,this.state应该包含一些内容,这些内容将确定是否应重新渲染该组件,以及this.props....我还不知道。

但是,当您最初调用时React.render(<MyComponent />, ...),只能传递道具。就我而言,我从服务器获取了所有数据,因此this.state无论如何,最初的道具最终还是会结束。所以我所有的组件都有这样的东西:

getInitialState: function() {
    return {
        progress: this.props.progress,
        latest_update: this.props.latest_update,
        nearest_center: this.props.nearest_center
    }
}

除非我对上述博客文章有误解,否则这是反模式。但是我看不到将状态注入Component的其他方法,而且我不明白为什么它是一种反模式,除非我重新标记所有道具以使其成为前提initial。如果有的话,我觉得那是一种反模式,因为现在我必须跟踪比以前更多的变量(带initial和不带)。


1
在2017年,Facebook演示了使用道具在其文档中设置初始状态的方法:reactjs.org/docs/react-component.html#constructor
Rohmer

1
@Rohmer的链接包含一个指向的链接,您可能不需要派生状态,其中对替代方法以及避免方法进行了深入讨论。
制造商史蒂夫(Steve),

Answers:


94

免责声明:当我回答这个问题时,我正在学习/尝试实现香草通量,对此我有些怀疑。后来我将所有内容迁移到Redux。因此,建议:只需使用Redux或MobX。您甚至可能不再需要该问题的答案(科学除外)。

将初始状态作为a传递给组件prop是一种反模式,因为该getInitialState方法仅在组件首次呈现时才调用。这意味着,如果您重新渲染该组件并传递另一个值作为a prop,则该组件将不会做出相应的反应,因为该组件将从首次渲染状态起就保持该状态。这很容易出错。

这是您应该做的:

尝试使您的组件尽可能无状态。无状态组件更易于测试,因为它们基于输入呈现输出。这样简单。

但是,嘿..我的组件数据发生了变化..我无法使它们成为无状态

是的,您可以,对于大多数人来说。为此,请选择一个外部组件作为状态持有者。使用您的示例,您可以创建一个Dashboard包含数据的Widget组件,以及一个完全无状态的组件。该Dashboard负责获取所有数据,然后呈现多个Widgets接收他们需要通过一切props

但是我的窗口小部件具有某种状态。用户可以对其进行配置。我如何使它们无状态?

Widget可以公开事件,这些事件在处理后会导致其中包含的状态Dashboard发生更改,从而导致每个事件都被Widget重新呈现。您可以Widget通过props接收功能来创建“事件” 。

好的,所以现在,仪表板保留状态,但是如何将初始状态传递给它?

您有两个选择。最推荐的Dashboard getInitialState方法是,您在方法中进行Ajax调用以从服务器获取初始状态。您还可以使用Flux,这是一种用于管理数据的更复杂的方法。助焊剂更多是一种模式,而不是一种实现。您可以在Facebook的实现中使用纯Flux Dispatcher,但可以使用ReduxAltFluxxor等第三方实现。

另外,您也可以将此初始状态作为传递prop给,例如Dashboard,明确声明这只是初始状态initialData。但是,如果选择此路径,则无法向后传递不同的初始状态,因为它会“记住”第一次渲染后的状态。

OBS

您的定义不太正确。

状态用于存储可变数据,即在组件生命周期中将要更改的数据。状态更改应通过setState方法进行,并将导致组件重新呈现。

道具用于将不可更改的数据传递到组件。它们在组件生命周期中不应更改。仅使用道具的组件是无状态的。

是“如何将初始状态传递给组件”的相关资料。


描述得非常好,但是……一如既往是“ but”。如果我有组件,该组件将获取图像数组并创建带有缩略图和onlick事件的子组件,该事件将更改该组件中的大图像,该怎么办。图像未处于状态,因此我无法使用其他组件来维护它。图像是本地的,我需要一些本地状态来管理,这些状态应显示为大图像。我很乐意在状态下使用道具,但会收到警告:setState(...):在现有状态转换期间(例如在内render)无法更新。渲染方法应该纯粹是props和state的函数。
卡尼亚

10
那么,对于使用componentWillReceiveProps(nextProps)状态设置有什么意见吗?
亚历杭德罗

1
从16.3开始不推荐使用componentWillRecieveProps(),所以...不。请不要使用它。
说唱时间

@Alejandro-您可能不需要派生状态是对使用(不推荐使用)componentWillReceiveProps或其替换(不推荐使用)的陷阱的深入解释getDerivedStateFromProps。底线:本文显示了几种替代解决方案,它们没有调用这些方法中的任何一种,并解释了为什么使用这些替代方法。
制造商
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.