ReactJS:为啥将组件初始状态传递给一个反模式?
Posted
技术标签:
【中文标题】ReactJS:为啥将组件初始状态传递给一个反模式?【英文标题】:ReactJS: Why is passing the component initial state a prop an anti-pattern?ReactJS:为什么将组件初始状态传递给一个反模式? 【发布时间】:2015-05-01 08:20:48 【问题描述】:我在 SocketIO 的帮助下创建了一个小型 ReactJS 仪表板,用于实时更新。即使我更新了仪表板,但我不确定我是否正确地更新了它。
最让我烦恼的是Props in getInitialState as anti-pattern 的帖子。我创建了一个仪表板,可以从服务器获取实时更新,除了加载页面之外不需要用户交互。根据我的阅读,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
除非我误解了上述博客文章,否则这是一种反模式。但是我看不到将状态注入组件的其他方法,我不明白为什么它是一种反模式,除非我重新标记所有道具以在它们前面加上 initial
。如果有的话,我觉得这是一种反模式,因为现在我必须跟踪比以前更多的变量(那些以initial
开头的变量和那些没有的变量)。
【问题讨论】:
2017 年,Facebook 在其文档中演示了使用道具设置初始状态:reactjs.org/docs/react-component.html#constructor @Rohmer 的链接包含指向You probably don't need derived state 的链接,其中深入讨论了替代方案以及应避免的事项。 【参考方案1】:免责声明:当我回答这个问题时,我正在学习/尝试 实施 vanilla Flux,我对此有点怀疑。后来我 将所有内容迁移到 Redux。所以,一个建议:只要使用 Redux 或 MobX。你可能甚至不需要这个问题的答案 不再是(科学除外)。
将初始状态作为prop
传递给组件是一种反模式,因为getInitialState
方法仅在组件第一次呈现时被调用。这意味着,如果您将 不同 值作为 prop
重新渲染该组件,该组件将不会做出相应的反应,因为该组件将保持第一次渲染时的状态。这很容易出错。
这是你应该做的:
尽量让你的组件无状态。无状态组件更容易测试,因为它们基于 输入 呈现 输出。就这么简单。
但是嘿..我的组件数据改变了..我不能让它们无状态
是的,对于大多数人来说,你可以。为此,请选择一个外部组件作为状态持有者。使用您的示例,您可以创建一个包含数据的 Dashboard
组件和一个完全无状态的 Widget
组件。 Dashboard
负责获取所有数据,然后渲染多个Widgets
,它们通过props
接收所需的一切。
但是我的小部件有一些状态.. 用户可以配置它们。如何使它们无国籍?
您的Widget
可以公开事件,这些事件在处理时会导致Dashboard
中包含的状态发生变化,从而导致每个Widget
都被重新呈现。通过让props
接收函数,您可以在Widget
中创建“事件”。
好的,现在,Dashboard 保持状态,但我如何将初始状态传递给它?
你有两个选择。最推荐的方法是在 Dashboard
getInitialState
方法中进行 Ajax 调用,以从服务器获取初始状态。您还可以使用Flux,这是一种更复杂的数据管理方式。 Flux 更像是一种模式,而不是一种实现。您可以将纯 Flux 与 Facebook 的 Dispatcher
实现一起使用,但您可以使用第三方实现,例如 Redux、Alt 或 Fluxxor。
或者,您可以将此初始状态作为prop
传递给Dashboard
,明确声明这只是初始状态.. 例如initialData
。但是,如果您选择此路径,则不能将不同的初始状态传递给它,因为它会“记住”第一次渲染后的状态。
OBS
你的定义不太对。
State 用于存储可变数据,即在组件生命周期中会发生变化的数据。状态的改变应该通过setState
方法进行,并且会导致组件重新渲染。
Props 用于将不可变数据传递给组件。它们不应在组件生命周期内更改。只使用 props 的组件是无状态的。
This 是“如何将初始状态传递给组件”的相关来源。
【讨论】:
它描述得很好,但是......一如既往地是一个“但是”。如果我有一个组件,它获取图像数组并创建带有缩略图和 onlick 事件的子组件,这应该改变这个组件中的大图像。图像未处于状态,因此我无法使用其他组件来维护它。图像是本地的,我需要一些本地状态来管理哪些应该显示为大图像。我很想在 state 中使用 props,但是会收到警告:setState(...): Cannot update during an existing state transition(例如在render
内)。渲染方法应该是 props 和 state 的纯函数。
那么,对于使用componentWillReceiveProps(nextProps)
设置状态有什么意见吗?
componentWillRecieveProps() 自 16.3 起已弃用,所以...不。不要使用它。
@Alejandro - You probably don't need derived state 是对使用(已弃用)componentWillReceiveProps
或其(未弃用)替换 getDerivedStateFromProps
的缺陷的深入解释。底线:文章展示了几种替代解决方案,不调用其中任何一种方法,并解释了为什么要使用这些替代方法。以上是关于ReactJS:为啥将组件初始状态传递给一个反模式?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 ReactJS 中将更改的状态从子组件传递给其父组件