- 译:101个React技巧#1组件组织
- 译:101个React技巧#2有效的设计模式与技术
- 译:101个React技巧#3Keys&Refs
- 译:101个React技巧#4组织React代码
- 译:101个React技巧#5高效状态管理
- 译:101个React技巧#6React代码优化
- 译:101个React技巧#7React代码调试技巧
- 译:101个React技巧#8测试 React代码
- 译:101个React技巧#9React hook
- 译:101个React技巧#10必知的React库/工具
- 译:101个React技巧#11React与Visual Studio Cod
- 译:101个React技巧#12React 与 TypeScript
- 译:101个React技巧#13其他技巧
15. 利用 children props 编写更简洁的代码(并获得性能优势)
使用 children props 有几个好处:
- 优势 #1:你可以避免 prop drilling,直接将 props 传递给子组件,而不是通过父组件路由。
- 优势 #2:你的代码更具扩展性,因为你可以轻松修改子组件而无需更改父组件。
- 优势 #3:你可以使用这个技巧来避免重新渲染"慢"组件(见下面的示例 👇)。
❌ 不好:每当 Dashboard 渲染时,MyVerySlowComponent 也会渲染,而 Dashboard 会在每次当前时间更新时重新渲染。你可以在下一张图片中看到这一点,我使用了 React 开发者工具的性能分析器。
function App() {
// 其他逻辑...
return <Dashboard />;
}
function Dashboard() {
const [currentTime, setCurrentTime] = useState(new Date());
useEffect(() => {
const intervalId = setInterval(() => {
setCurrentTime(new Date());
}, 1_000);
return () => clearInterval(intervalId);
}, []);
return (
<>
<h1>{currentTime.toTimeString()}</h1>
<MyVerySlowComponent /> {/* 每当 `Dashboard` 渲染时都会渲染 */}
</>
);
}
MyVerySlowComponent 每当 Dashboard 渲染时都会渲染
✅ 好:MyVerySlowComponent 不会在 Dashboard 渲染时重新渲染。
function App() {
return (
<Dashboard>
<MyVerySlowComponent />
</Dashboard>
);
}
function Dashboard({ children }) {
const [currentTime, setCurrentTime] = useState(new Date());
useEffect(() => {
const intervalId = setInterval(() => {
setCurrentTime(new Date());
}, 1_000);
return () => clearInterval(intervalId);
}, []);
return (
<>
<h1>{currentTime.toTimeString()}</h1>
{children}
</>
);
}
MyVerySlowComponent 不再重新渲染
16. 使用 compound components 构建可组合的代码
将复合组件想象成 乐高 积木。
你可以将它们拼在一起创建自定义 UI。这些组件在创建库时特别有效,可以产生既富有表现力又高度可扩展的代码。
你可以在这里进一步探索这种模式 👉 复合模式
来自 reach.ui 的示例(Menu、MenuButton、MenuList、MenuLink 是复合组件)
<Menu>
<MenuButton>
操作 <span aria-hidden>▾</span>
</MenuButton>
<MenuList>
<MenuItem onSelect={() => alert("下载")}>下载</MenuItem>
<MenuItem onSelect={() => alert("复制")}>创建副本</MenuItem>
<MenuLink as="a" href="https://reacttraining.com/workshops/">
参加研讨会
</MenuLink>
</MenuList>
</Menu>
17. 使用 render functions 或 component functions props 使代码更具扩展性
假设我们想要显示各种列表,如消息、个人资料或帖子,每个列表都应该是可排序的。
为了实现这一点,我们引入了一个可复用的 List 组件。有两种方法可以实现:
❌ 不好:选项 1
List 处理每个项目的渲染和排序方式。这有问题,因为它违反了开闭原则。每当添加新的项目类型时,这段代码都需要修改。
✅ 好:选项 2
List 接受渲染函数或组件函数,仅在需要时调用它们。
你可以在下面的沙盒中找到示例 👇:
18. 处理不同情况时,使用 value === case && <Component /> 避免保留旧状态
❌ 问题:在下面的沙盒中,当在 Posts 和 Snippets 之间切换时,计数器不会重置。这是因为当渲染相同的组件时,其状态会在类型更改时保持不变。
✅ 解决方案:根据 selectedType 渲染组件,或使用 key 在类型更改时强制重置。
function App() {
const [selectedType, setSelectedType] = useState < ResourceType > "posts";
return (
<>
<Navbar selectedType={selectedType} onSelectType={setSelectedType} />
{selectedType === "posts" && <Resource type="posts" />}
{selectedType === "snippets" && <Resource type="snippets" />}
</>
);
}
// 我们使用 `selectedType` 作为 key
function App() {
const [selectedType, setSelectedType] = useState < ResourceType > "posts";
return (
<>
<Navbar selectedType={selectedType} onSelectType={setSelectedType} />
<Resource type={selectedType} key={selectedType} />
</>
);
}
19. 始终使用错误边界
默认情况下,如果你的应用程序在渲染过程中遇到错误,整个 UI 会崩溃 💥。
为了防止这种情况,使用错误边界来:
- 即使发生错误,也能保持部分应用功能正常。
- 显示用户友好的错误消息,并可选择跟踪错误。
💡 提示:你可以使用 react-error-boundary 库。