把每一份状态放在最近的公共祖先中,从而在多个组件之间共享数据而不重复它。
在 Kodokon 中打开本课两个兄弟组件需要显示同一份数据:例如一个搜索框和它所过滤的列表。在各自内部使用局部状态是行不通的,因为它们彼此看不见。解决办法是把状态提升到它们最近的公共祖先中:由父组件持有数据,再通过 props 把它传回下去。
import { useState } from "react";
function ProductPage({ products }) {
const [query, setQuery] = useState("");
return (
<>
<SearchBar query={query} onChange={setQuery} />
<ProductList products={products} query={query} />
</>
);
}于是子组件就成为了受控组件:它们以只读方式接收该值,若要修改它,就调用父组件提供的回调函数。数据通过 props 向下流动,变更请求通过函数向上流动。这种单向流动让应用的行为易于追踪。
function SearchBar({ query, onChange }) {
return (
<input
value={query}
onChange={(e) => onChange(e.target.value)}
placeholder="Search for a product"
/>
);
}
function ProductList({ products, query }) {
const visible = products.filter((p) =>
p.name.toLowerCase().includes(query.toLowerCase())
);
return (
<ul>
{visible.map((p) => <li key={p.id}>{p.name}</li>)}
</ul>
);
}每一份数据都必须有唯一的数据来源。如果两个组件各自存储同一份状态的副本,这些副本迟早会不一致:一个被更新了,另一个没有,界面就变得前后矛盾。状态提升消除了这种风险。当数据需要跨越很多层时,组合(下一课)以及随后的 context 会减轻 props 的层层传递。