我应该在父组件中保留状态还是在父子组件之间共享状态?React.js

4
假设我有一个父组件,它将用户设置保存在其状态中,并通过将其作为对象传递给所有子组件来同步应用程序中的设置。为了论证,假设有两个其他子组件,一个称为组件,其中包含一个表单,用户在其中输入其设置并单击提交以提交其设置。另一个组件根据用户在早期表单中为应用程序选择的设置显示/隐藏各种元素或其他组件。这两个组件不会同时呈现,只有用户提交表单后才会显示组件。
现在,我发现自己陷入两种方法之间:一种是在组件内部也保留所有设置状态,并且每当输入更改时,只相应地更新组件状态,通过为每个输入提供处理程序,在用户提交表单后仅通过回调(将更新组件的状态)将所有这些设置传递到组件。 或者,使成为无状态组件,并将所有输入处理程序作为回调(或作为一个统一的回调)传递给组件,然后在每次输入更改时更新状态。
作为一个老派的Web开发人员,我更喜欢第一种方法,因为它只更新一次组件,因此只重新呈现其所有子组件一次,而我的组件仍然独立于组件,并且它们的唯一接口是回调,一次传递整个设置对象。
另一方面,第二种方法将所有逻辑和处理从组件中分离出来,消除了冗余状态,并将其作为一个简单的UI“视图”组件。这看起来像我见过的许多React应用程序中使用的常见设计模式。
哪种方法更好,为什么?我还错过了什么吗?您如何处理此问题?在React中,父子交互的最佳实践是什么?您希望子组件与其环境封装和独立程度有多高? 您希望从父级传递多少个回调?
我也会非常感激一些好的参考和阅读材料。
谢谢。

Redux是您的解决方案。尽管这肯定需要您学习一些知识。 - Dan Zuzevich
谢谢,我同意其他人建议的Redux、Mobx或Flux模式方法可能会终止对回调的需求。但我觉得这对于一个简单的问题来说有点过度杀伤力了,据我所知,Redux和其他框架只在数据流量很大的情况下才需要使用。我在这里描述的问题相当简单——它有一个非常简单的表单,并从中生成一个对象,该对象仅从单个子级流向父级,然后必须从父级向所有子级流动,因此将其与数据存储连接起来似乎有些夸张,你不觉得吗? - Avi Gurfinkel
3个回答

2
在React中,总是首选将状态放在顶层组件和无状态子组件中。关于回调函数,最好的方法是向下传递“相关”的回调函数。什么算是“相关”很主观,但可读性必须是最重要的且回调函数对于子组件也必须是相关的。
在我们的大型代码库中,我们最多只有3个回调函数,并且从最上层组件到嵌套的组件最多只有2级。我们广泛使用ES6解构、不可变助手以及三个点操作符...来管理顶层组件的状态(从子组件接收数据),并将所有子组件保持为无状态组件。
这使我们能够提高测试效率,提高组件的覆盖率。无状态组件使得组件更易于阅读和性能更佳。
如果您的组件需要向下传递“事件”而不是状态(数据),或者您的嵌套级别超过2且代码难以维护,则必须探讨类似Redux的状态管理框架。
谢谢, Sriram

谢谢,听起来是个不错的经验法则。你知道无状态子组件方法是仅为了可读性还是也可能存在偏好问题吗?你有任何支持这些说法的来源吗? - Avi Gurfinkel
1
React 16(fiber)被认为具有较小的性能改进(参考:Twitter线程https://twitter.com/dan_abramov/status/755343749983657986,作者为Dan Abramov)。请参考“无状态功能组件”部分,其中提到了过去“要进行的性能改进”。 https://reactjs.org/blog/2015/09/10/react-v0.14-rc1.html#stateless-function-components。 - Sri
@Sri,你能指出Fiber中实际的性能改进吗?我敢打赌你做不到,这是将来的事情,而不是React 16中的事情(例如,请查看官方更改日志https://reactjs.org/blog/2017/09/26/react-v16.0.html)。 - Andy Theos
@AndyTheos 我在 Dan 的推文中注意到了一些微小的改进(我已经引用过了)。16 没有官方发布说明,因此我提到了“据理解”。 - Sri

0

这个问题非常广泛,你需要提供至少一个MVP才能得到一些实际的答案。

官方文档永远是最好的选择:

将状态提升

React中的思考


谢谢您的回答,我一定会查看这些链接...我故意没有在问题中添加任何代码,因为这可能会导致大量的代码,偏离问题本身到实际解决方案,而我想保持它作为一个抽象的论点,探讨哪种方法会导致更好的设计。我会尝试制作一些基本的示例。 - Avi Gurfinkel
是的,我正是让你尝试用基本的例子来解决这个问题,也许就像你提到的App->[设置,Foo]的天真实现一样。 - Andy Theos

0

我建议使用flux模式,您可以将状态放入数据存储中,允许组件共享数据并监视更改,这将避免处理程序和级联属性的爆炸。


谢谢您的回答,但我认为这可能对于一个基本和简单的应用程序来说有些过度。假设我想继续使用React的原始单向数据流而不添加任何内容,并且假设级联到组件的唯一数据是“设置”对象,我认为构建数据存储以保存它有点过度设计了……?只是为了明确问题,哪种方法会更好,为什么?将所有数据一次性更新到父级,并将其保留在子级状态中,或者从子级不断更新父级。 - Avi Gurfinkel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接