Javascript ReactJs的功能风格打破了封装

Javascript ReactJs的功能风格打破了封装,javascript,reactjs,Javascript,Reactjs,我弄不好。事情是这样的:我制作了两个小部件,一个TabBar和一个TabNavigator。选项卡导航包含索引为currentSelectedTab的状态。因此,当TabBar收到用户单击时,它会通知父级(TabNav)做一些事情(通过回调),而父级会准确地注入新的道具,说:亲爱的TabBar,选择这个选项卡:currentSelectedTab 同时,tabNav为选项卡显示正确的内容 到目前为止还不错。但是,现在我希望应用程序能够将TabNav设置为特定的选项卡。作为道具,我一介绍它,它就打

我弄不好。事情是这样的:我制作了两个小部件,一个TabBar和一个TabNavigator。选项卡导航包含索引为currentSelectedTab的状态。因此,当TabBar收到用户单击时,它会通知父级(TabNav)做一些事情(通过回调),而父级会准确地注入新的道具,说:亲爱的TabBar,选择这个选项卡:currentSelectedTab 同时,tabNav为选项卡显示正确的内容

到目前为止还不错。但是,现在我希望应用程序能够将TabNav设置为特定的选项卡。作为道具,我一介绍它,它就打破了选项卡nav中currentSelectedTab的封装。它必须在应用程序外部定义。这太糟糕了

在OOP透视图中,我会在小部件TabNav中使用setCurrentTab,但在FP中,特别是在React中,这是禁止的。小部件的唯一入口是道具。(裁判是邪恶的,对吧?)

这意味着当TabBar接收到用户单击时,它将调用TabNav中的回调,并且TabNav还必须调用应用程序中定义的上层回调。然后这个回调将更改应用程序状态,并设置currentSelectedTab,因此它将通过props传递到TabNav

currentSelectedTab必须在TabNav之外定义这一事实非常可怕。你不这么认为吗?在我看来,它破坏了组件封装。如何正确地做到这一点?通量?同样的道理:currentSelectedTab不必在全局状态中定义

基本上,如果一切都正常运行,最终会出现一个巨大的状态,其中包含属于某些小部件的内容。封装被彻底破坏了


也许有人能给我解释一下这里出了什么问题?

使用命令式语言设置所选选项卡的公共方法与使用prop在react中执行相同的操作没有太大区别

一旦您觉得需要控制组件之外的某些财产,它自然会成为其公共合同的一部分。在react中,这主要是公共类方法/字段,最好是公共OOP语言中的道具

不过,react prop没有必要直接表示其内部状态。使用道具作为状态的初始值是完全可以的。甚至还有一个特殊的钩子,它允许你在道具改变时改变你封装的内部状态


希望这能澄清一些问题。

我找到了正确的解决方法。 应用程序的职责只是提供初始值。因此我将我的道具命名为:initialSelectedTabIndex TabNavigator是当前索引的所有者,而不是应用程序的所有者,它将使用TabBar上的回调来做正确的事情(更新其内部状态,其中包含类似于selectedTabIndex的内容)。 这样就不会破坏封装。应用程序不必使用回调来重新发送新索引,而是由TabNav来完成


组件将接收TabNav中出现的道具时,我什么也不做。因为我不想用props initialSelectedTabIndex覆盖内部状态,因为它不再是一个初始化。

一些代码将有助于可视化您正在进行的操作。
TabNavigator
提供了哪些无法在
选项卡中干净处理的功能?我很难想象为什么不能让选项卡栏处理导航并向其传递
defaultSelectedTab
prop。事实上,他们两人的名字中都有Tab,这似乎表明他们已经很般配了。您是否打算将TabBar重新用于其他用途?通用用例是什么?这是一种常见的做事方式。例如,在flex中。看见他们的ViewStack是我的TabNav,他们的ButtonBar是我的TabBarI尝试过的组件将接收道具,我认为问题在于没有中间解决方案。我不能说“我在道具中传递了当前选项卡索引”,同时说“我在状态中使用了当前选项卡索引”。我有这样一个错误:我通过道具将0作为小部件的起始索引传递,然后单击选项卡,进入选项卡2,然后由于某种原因在应用程序中发生重新渲染,因此之前的道具“0”通过“componentWillReceiveProps”进入,并覆盖当前状态“1”。所以我无缘无故地离开了当前选项卡。componentWillReceiveProps接受
nextProps
参数。您可以检查nextProps.selectedTabIndex与当前索引相比是否发生了更改,然后才更新状态。这完全等同于调用public方法来强制更改索引。即使没有理由调用它,也不会每次都使用相同的索引调用它。相反,只有当您知道发生了变化时才调用它。使用道具时,组件只有在知道其道具(公共“接口”)进行了必要的更改时才会改变其状态。这不起作用。在我的例子中,不推荐使用nextrops.selectedTabIndex。因为我还没决定这东西的主人在哪里。如果它是应用程序,它会工作,小部件只会通知应用程序它必须更改。一旦你决定在状态下管理它,封装它,它就不工作,应用程序不同步。不能将此字段存储在两个位置。