这是我参与2022首次更文挑战的第23天,活动详情查看:2022首次更文挑战。
以结果为导向,写给刚学完前端三剑客和想要了解 React 框架的小伙伴,使得他们能快速上手(省略了历史以及一些不必要的介绍)。
状态提升
虽然我们创建了一个回调函数来将信息向上共享,但我们的目标是在多个组件中共享 Search 组件的 state。
在将 stories 传递给 List 组件之前,我们需要在 App 组件中【使用用户输入来过滤列表】,所以 state 要从子组件 Search 提升到父组件 App,以便更多组件共享 state。
也就是说 Search 组件不再管理 state,只需要在用户输入后,将事件向上传递给父组件 App:
const App = () => {
const stories = [ ... ];
// 状态提升
const [searchTerm, setSearchTerm] = React.useState("");
const handleSearch = (e) => {
setSearchTerm(e.target.value);
};
return (
<div>
<Search onSearch={handleSearch} />
<hr />
<List list={stories} />
</div>
);
};
const Search = (props) => (
<div>
<label htmlFor="search">Search: </label>
<input id="search" type="text" onChange={props.onSearch} />
</div>
);
当然你也可以将 searchTerm
作为 props 向下传递,继续在 Search 组件中展示:
const App = () => {
...
return (
<div>
<Search onSearch={handleSearch} searchTerm={searchTerm}/>
...
</div>
);
};
const Search = (props) => (
<div>
<label htmlFor="search">Search: </label>
<input id="search" type="text" onChange={props.onSearch} />
<p>
Searching for <strong>{props.searchTerm}</strong>.
</p>
</div>
);
总之如果下游的组件要使用 state,可以将其作为 props 传递;如果下游组件要更新 state,可以向下传递一个回调处理函数。【可参考 Search 组件】
然后就是通过 searchTerm
值 ,使用 JS内置的数组过滤函数 来过滤列表,同时做了【大小写不敏感】的匹配:
const App = () => {
...
const searchedStories = stories.filter((story) =>
story.title.toLowerCase().includes(searchTerm.toLowerCase())
);
return (
<div>
<Search onSearch={handleSearch} searchTerm={searchTerm} />
<hr />
<List list={searchedStories} />
</div>
);
};
Array.filter()
接收一个函数作为参数,并返回一个全新的数组。
该函数遍历数组的每一项并返回 true 或 false,如果返回 true,则代表该项满足条件,会保存到新数组中,反之则不保存,遍历完成后返回新数组。
现在你已经可以在输入框输入来进行搜索了,通过 Search 组件的回调处理函数,我们在 App 组件中更新了 state,并通过 state 过滤了列表传递给了 List 组件。
React fragment
你可能会注意到:当我们创建 Search 组件时,必须引入一个顶层的 HTML 元素把它包起来才能渲染:
const Search = (props) => (
<div>
<label htmlFor="search">Search: </label>
<input id="search" type="text" onChange={props.onSearch} />
<p>
Searching for <strong>{props.searchTerm}</strong>.
</p>
</div>
);
这是因为 React 组件返回的 JSX 虽然看起来像 HTML,但它在底层会被转换为【纯 JS 对象】,如果有多个同级的顶层元素,我们必须把它们放在数组中,而且加上 key 属性,以便从函数中返回多个对象:
// 举例
const Search = () => [
<input key="1" />,
<input key="2" />,
];
当然我们有另一种简洁的解决方式,就是 React fragment:
const Search = (props) => (
<>
<label htmlFor="search">Search: </label>
<input id="search" type="text" onChange={props.onSearch} />
<p>
Searching for <strong>{props.searchTerm}</strong>.
</p>
</>
);
这个空的 tag 就是所谓的 fragment,像这样替换掉 div 就可以让你在 HTML 树中【不留痕迹】地对事物进行分组了。
专栏
因为参加打卡活动是每日更新,所以可能比较短小,可以关注一下 React 入门专栏。
在更新完后会整合为一整篇,感谢关注和点赞!