我从创建 React Hook 库中学到的 10 件事
我建造的
介绍 React Final Table
1. React Hooks 非常棒
2. TSDX 让开发变得轻而易举
3. React Testing Library 让测试变得轻而易举
4. 使用沙盒示例
5. Hooks 的功能远不止 useState 和 useEffect。
6. 无头 UI 组件 > UI 组件
7. 使用 TypeScript 泛型来构建灵活的库
8. GitHub Actions 和持续集成至关重要
9. 从开源软件中学习
10. 解决你自己的问题
由 Mux 主办的 DEV 全球展示挑战赛:展示你的项目!
自React 16.8引入Hooks以来, Hook 库如雨后春笋般涌现,这并非偶然。Hooks 让函数式组件能够重用代码。如果没有 Hooks,函数式组件就无法成为类组件的可行替代方案。
虽然我之前也做过自定义 Hook,但我一直拖延着没做自己的 React Hook 库。我知道,如果我做了自定义 Hook 却不把它做成库,它最终只会躺在我 GitHub 仓库里那些未完成的业余项目堆里,无人问津。所以我需要把它做成可共享的,这样才能督促自己坚持下去。
我建造的
我对现有的表格库感到非常失望。在我的大多数项目中,我都需要以某种形式展示表格数据。虽然大多数现有的表格库都能胜任,但一旦你偏离默认的用户界面,就会发现它们难以兼容。这些表格库存在大量问题,因为很难设计出真正能够灵活应对所有使用场景的用户界面。
我需要一种简单易用的方法来管理表格状态,并且不希望界面有任何预设。偶然间,我发现了无头组件的概念,它似乎完美契合我的需求。本质上,无头组件提供了管理组件状态的工具,而不会预设任何用户界面样式。
介绍 React Final Table
基于这个概念,我开发了React Final Table。它是一个极其轻量级(压缩后仅 1.5KB,且无任何依赖)、类型安全、无头的组件库,仅暴露一个 Hook。它开箱即用,支持表格的筛选、搜索、选择、排序和分页功能。其最基本的实现方式如下:
import { useTable } from 'react-final-table';
const columns = [
{
name: 'firstName',
label: 'First Name',
render: ({ value }) => <h1>{value}</h1>,
},
{
name: 'lastName',
label: 'Last Name',
},
];
const data = [
{
firstName: 'Frodo',
lastName: 'Baggins',
},
{
firstName: 'Samwise',
lastName: 'Gamgee',
},
];
const MyTable = () => {
const { headers, rows } = useTable(columns, data);
return (
<table>
<thead>
<tr>
{headers.map((header, idx) => (
<th key={idx}>{header.render()}</th>
))}
</tr>
</thead>
<tbody>
{rows.map((row, idx) => (
<tr key={idx}>
{row.cells.map((cell, idx) => (
<td key={idx}>{cell.render()}</td>
))}
</tr>
))}
</tbody>
</table>
);
};
请参阅文档以获取更多示例用例。
废话不多说,以下是我在此过程中学到的最重要的几点:
1. React Hooks 非常棒
React 中与可复用函数类似的机制是 Hooks。任何需要在组件间重复编写非 UI 代码的地方,都应该评估是否值得创建一个自定义 Hook。身份验证和数据获取是最常见的应用场景。
2. TSDX 让开发变得轻而易举
TSDX是一个用于快速开发 TypeScript 包的库。它提供了一个 React 模板,这意味着只需几秒钟即可开始创建一个新包。更多信息请参阅我的 TSDX 使用指南。
3. React Testing Library 让测试变得轻而易举
虽然我非常喜欢用 Python、Jest 进行测试,甚至用 Cypress 进行端到端测试,但我不太确定如何才能最好地对前端进行集成测试。我知道我不想把所有功能都拆分成单元测试,因为我真正想测试的是它是否能按预期运行,而与实现细节无关。
React Testing Library让测试 React Hooks 变得简单,无需测试其具体实现。这意味着我的测试能够模拟用户实际使用库的方式,并且不会因代码库的更改而变得脆弱。
4. 使用沙盒示例
测试固然重要,但它只能帮你完成一部分工作。有时,你需要直观地查看添加功能时发生的情况。为此,设置几个使用你尚未发布的库的沙盒示例至关重要。你可以使用npm link`<link>`(或 `<link> `)链接到你尚未发布的库。发布版本后,你可以使用Codesandbox.ioyarn link的链接分享沙盒示例。以下是使用 Codesandbox 实现的 React Final Table示例。
或者更好的办法是,搭建一个包含大量示例用例的Storybook。Storybook允许你独立开发多个组件,并生成相应的文档。
5. Hooks 的功能远不止 useState 和 useEffect。
虽然我们一开始都会过度使用像 useState 和 useEffect 这样的 Hooks,但还有很多其他的 Hooks 需要注意。
我最喜欢的一些不太常见的 Hooks 包括 useReducer(用于处理复杂状态)、useMemo/useCallback(用于提升性能)和 useRef(用于在渲染生命周期之外持久化更改)。在这个库中,我大量使用了所有这些 Hooks。
6. 无头 UI 组件 > UI 组件
根据我的个人经验,无头 UI 组件更能适应变化,也更容易重构。使用预制的 UI 组件库看似方便,但如果你需要对其进行大量自定义,那就需要三思。它最终可能会带来比你预期更多的工作量。
7. 使用 TypeScript 泛型来构建灵活的库
为了创建一个灵活的 TypeScript 库,我必须确保允许用户在表中存储任何类型的数据。但是,如何在不any处处使用类型定义的情况下安全地做到这一点呢?
这就是泛型的作用所在。泛型允许我们在运行时指定类型,同时还能确保 TypeScript 执行类型安全检查。以下代码片段详细说明了泛型的概念:
// this function takes an element of any type and returns that same type
function identity<T>(arg: T): T {
return arg;
}
console.log(typeof identity(42)); // number
console.log(typeof identity('string')); // string
console.log(typeof identity(undefined)); // undefined
8. GitHub Actions 和持续集成至关重要
如果你在个人或工作项目中还没有使用持续集成,那你绝对应该开始尝试了。我以前是CircleCI 的重度用户,但最近我开始更喜欢GitHub Actions。Actions的配置和集成比 CircleCI 简单得多,而且预构建的 Action 生态系统也更加丰富。在 React Final Table 项目中,除了 ESLint、Prettier 和测试步骤之外,我还添加了一个 GitHub Action 来运行代码覆盖率,以及另一个 Action 来根据提交信息自动发布到 NPM。这极大地简化了我的开发流程,因为我不再需要每次修改后都手动更新版本号并发布到 npm。
9. 从开源软件中学习
我经常从我喜欢的开源项目中汲取关于架构、最佳实践和贡献实践的灵感。其中一些对这个库很有帮助的项目包括downshift(另一个无头 UI 库)、react-hook-form和react-query。
10. 解决你自己的问题
我最后的建议是,开发库时一定要考虑解决你遇到的问题。没有什么比开发自己用不到的东西更打击积极性的了,所以务必确保你会是这个库的主要用户之一。
通过创造你需要的东西,你也会对自己的藏书产生归属感,并且更有可能创造出更有价值的东西。
文章来源:https://dev.to/g_abud/10-things-i-learned-by-making-a-react-hook-library-4i0a