一、概念
组件可以通过props和state来包含数据:
- props是一个组件的配置信息。它们是从组件的上层传递而来,在组件接收到之后就保持不变。
- state一开始在组件构造函数中被设置为一个默认值,然后随着组件的执行而不断变化(通常都是由于用户的操作而导致)。一个组件在内部管理它自己的state,每当state变化时,组件就重新渲染。
对于React的组件而言,state是可选的。在大部分React应用程序中组件分成两类:一类组件有state(称为有状态组件),另一类则没有内部state,只负责数据的显示(称为无状态组件)。
无状态组件只接收props,然后负责将这些props渲染到一个视图中。这个特性使得无状态组件很容易被复用和被测试。
然而,有时需要响应用户的输入,或是一个服务器请求,或是时间的流逝。这样你就需要使用state。有状态组件通常具有更高的组件层级,也就是说,它们通常包装了一个或多个有状态或无状态组件。
让一个应用程序的大部分组件都是无状态的单纯组件是一个最佳实践。如果应用程序的state在多个组件之间传播,会导致它难以跟踪。由于应用程序的工作方式变得更不清晰,也降低了程序代码的可预测性。这会在代码中潜在地引入一些难以理清和解决的情况。
二、哪些组件应当是有状态组件
如果不清楚如何确定应该由哪个组件来拥有某个state数据,可按下面的四步代码清单来一一对照。对于你的应用程序的每一个state:
- 标识出基于那个state来进行渲染的每一个组件。
- 找到一个通用的owner组件(在组件层级中,位于所有需要那个state的组件之上的单个组件)。
- 通用的owner组件或者更高层级的另一个组件应当拥有那个state。
- 如果你无法找到一个合理的拥有state的组件,创建一个新组件来拥有state,然后在组件层级中,将它添加到所有需要那个state的组件上的某个位置。
为演示上面的步骤,下面创建一个非常简单的应用程序,带搜索功能的表格如下:
这个应用程序的组件层级是:
|——TableApp:主组件(owner组件)
|————SearchBar:搜索输入框(需要显示出搜索文本)
|————TableWrap:遍历数据,创建一系列TableState组件(需要基于state来筛选数据)
|——————TableState:显示表格数据
将TableApp设置为有状态组件,其他为无状态组件是符合逻辑的。TableApp之后会将筛选文本以props的方式向下传递给子组件。SearchBar组件将使用其作为文本框的值,TableWrap组件将使用它筛选联系人数据。
三、组件通信
在上述例子中,state属于顶层组件TableApp,它通过props向下传递给下层的SearchBar组件和TableWrap组件。
如果想要确保用户无论何时更改搜索内容时,都能基于用户输入的更新的搜索文本来更新state,这就涉及到了组件之间的通信问题(子组件向父组件传递信息)。
React的通信机制:react中,数据流是单向的,数据总是沿着一个方向,即从父组件向子组件流动。父组件可将一个回调函数作为props向下传递给子组件,这样子组件就可以使用接收到的回调函数将数据传回上层。