ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

react-use 导入方式完全指南:单独导入、ESM 命名导入与 babel-plugin-import 自动转换

react-use 导入方式完全指南:单独导入、ESM 命名导入与 babel-plugin-import 自动转换 react-use 导入方式完全指南单独导入、ESM 命名导入与 babel-plugin-import 自动转换【免费下载链接】react-useReact Hooks — 项目地址: https://gitcode.com/gh_mirrors/re/react-use本篇指南系统讲解 react-use 的安装前提与全部导入方式从逐 hook 单独导入、支持 tree shaking 的 ES6 命名导入到如何借助babel-plugin-import在保留命名导入写法的同时自动转换为单独导入。读完本文你将能够根据自己的打包器Webpack、Rollup、Vite 等与工程约束选择最稳定、体积最优的引入方案并彻底理解 react-use 的lib/esm/lib/component/lib/factory目录结构为何决定了这些导入规则的差异。环境要求React 16.8.0 及以上react-use 是一套基于官方 Hooks API 的 React Hooks 集合因此使用它的前提是项目中已经安装了支持 Hooks 的 React 版本。官方使用文档明确要求You need to have React16.8.0or later installed to use the Hooks API.即React 16.8.0 或更高版本该版本首次引入了useState、useEffect、useReducer等内置 Hook。这一点也可以在仓库的 package.json 中得到印证react-use 将react与react-dom声明为peerDependencies且版本为*意味着它不自己捆绑 React而是复用宿主项目中的 React 实例——这正是 Hooks 能够工作的前提同一份 React 运行时、同一份 Fiber 调度。方式一逐 hook 单独导入官方推荐react-use 允许并且鼓励按需单独导入单个 Hook直接指向编译产物目录import useToggle from react-use/lib/useToggle这种写法的特点是路径直接落到lib/下的具体模块文件例如lib/useToggle.js打包器只会把该 Hook 及其依赖打进 bundle不会引入lib/index.js中其余上百个 Hook不依赖打包器的 tree shaking 能力任何打包器都能精确裁剪体积不会触发下文提到的 peer dependency 报错。对应到源码src/useToggle.ts 的完整实现极其精简它就是基于 React 内置useReducer的一层封装import { Reducer, useReducer } from react; const toggleReducer (state: boolean, nextValue?: any) typeof nextValue boolean ? nextValue : !state; const useToggle (initialValue: boolean): [boolean, (nextValue?: any) void] { return useReducerReducerboolean, any(toggleReducer, initialValue); }; export default useToggle;从这里可以看出 react-use 的模块设计风格每个 Hook 都是一个独立的、default export的模块天然为逐文件导入做好了准备。方式二ES6 命名导入tree shaking 推荐如果你希望统一从包入口导入可以使用 ES6 命名导入import { useToggle } from react-use使用这种写法时依赖打包器对 ESM 的 tree shaking 能力来剔除未使用的导出。react-use 为此做了充分铺垫在 package.json 中可以看到main: lib/index.js—— CommonJS 产物入口tsc编译产出对应脚本build:cjsmodule: esm/index.js—— ESM 产物入口tsc -m esNext --outDir esm产出对应脚本build:es供支持module字段的打包器Webpack、Rollup、Parcel 等优先使用sideEffects: false—— 显式声明所有模块无副作用允许打包器安全地摇掉未使用的导出。完整的导出清单集中在 src/index.ts它通过export { default as xxx } from ./xxx的方式批量转出全部 HookuseToggle、useCounter、useLocalStorage、useAsync等同时也会转出createGlobalState、createBreakpoint、createMemo等工厂函数。为什么命名导入可能报 missing dependency error使用文档特别提醒了一类常见问题Depending on your bundler you might run into a missing dependency error with ES6 named import statements. Some hooks require you to install peer dependencies so we recommend using individual imports.意思是某些打包器在使用 ES6 命名导入时可能会报缺少依赖的错误。原因在于 react-use 中个别 Hook 依赖了额外的第三方运行时而这些依赖并未随 react-use 一起安装它们以 peer dependency 的形式存在或仅作为开发依赖存在。源码是最直接的证据。在 src/index.ts 中可以看到// not exported because of peer dependency // export { default as useKeyboardJs } from ./useKeyboardJs;useKeyboardJs因为依赖keyboardjs而没有从入口导出同样地src/index.ts 也注释掉了useSpring// not exported because of peer dependency // export { default as useSpring } from ./useSpring;useSpring依赖react-spring它出现在仓库的 package.json 的devDependencies中useKeyboardJs依赖keyboardjs同样位于devDependencies。这些 Hook 只能通过单独导入的方式使用并且要求你在自己的项目中自行安装对应依赖。正因如此使用文档给出的结论是官方推荐使用单独导入individual imports以规避这些边界情况。两全其美babel-plugin-import 自动转换既想保留import { useToggle } from react-use的优雅写法又希望获得单独导入的稳定性与精确裁剪使用文档给出的方案是引入babel-plugin-import让 Babel 在编译期把命名导入自动改写为单独导入。配置写在.babelrc中[ import, { libraryName: react-use, camel2DashComponentName: false, customName(name) { const libraryDirectory name.startsWith(Use) ? lib/component : name.startsWith(create) ? lib/factory : lib return react-use/${libraryDirectory}/${name} } }, import-react-use ]配置项逐条说明配置项取值作用libraryNamereact-use声明要转换的包名Babel 只处理来自react-use的导入语句camel2DashComponentNamefalse关闭驼峰转短横线的默认行为保证useToggle、createGlobalState等名称原样保留不变成use-toggle、create-global-statecustomName函数自定义导入路径的生成规则核心逻辑是把不同前缀的导出映射到不同的产物子目录插件数组末位import-react-use该 Babel 插件实例的自定义名称便于在报错与调试时区分多个import插件实例其中customName是整个配置的关键它揭示了 react-use 产物的目录分治策略name.startsWith(Use)→lib/component以Use开头的导出是组件而非 Hook。仓库中对应的真实产物来自 src/component/UseKey.tsx它通过createRenderProp工厂见 src/factory/createRenderProp.ts把useKey包装成 Render Prop 组件name.startsWith(create)→lib/factory以create开头的是工厂函数例如createGlobalState、createBreakpoint、createMemo、createReducer、createStateContext等它们统一编译到lib/factory子目录源码对应 src/factory/ 目录其余 →lib绝大多数普通 HookuseToggle、useAsync、useLocalStorage等直接位于lib/根目录源码对应 src/ 目录下的各.ts文件。这样一来import { useToggle } from react-use会被转换为import useToggle from react-use/lib/useToggleimport { createGlobalState } from react-use会被转换为import createGlobalState from react-use/lib/factory/createGlobalStateimport { UseKey } from react-use则会被转换为import UseKey from react-use/lib/component/UseKey。整个转换在编译期完成运行时零开销。目录结构速览理解导入规则的地图理解上面三条映射规则只需对照仓库的源码目录组织方式src/ ├── component/ # 组件如 UseKey.tsx→ lib/component │ └── UseKey.tsx ├── factory/ # 工厂函数如 createGlobalState.ts→ lib/factory │ ├── createBreakpoint.ts │ ├── createGlobalState.ts │ ├── createMemo.ts │ └── ... ├── index.ts # 总出口汇总全部命名导出 ├── useToggle.ts # 普通 Hook → lib/ ├── useAsync.ts └── ...编译脚本在 package.json 中定义为build: cjstsc输出到lib/与build: estsc -m esNext输出到esm/TypeScript 编译选项见 tsconfig.json。也就是说lib/与esm/是同一套源码的两份产物前者是 CommonJS供 Node 环境与不支持 ESM 的打包器使用后者是 ES Module供支持 tree shaking 的打包器使用。小结与选型建议方案写法适用场景单独导入import useToggle from react-use/lib/useToggle官方推荐、最稳妥不依赖 tree shaking可安全使用useKeyboardJs、useSpring等需要额外 peer dependency 的 Hook命名导入import { useToggle } from react-use写法统一、依赖打包器 tree shakingsideEffects: false已声明现代打包器可正确摇树babel-plugin-import源码写命名导入编译期自动转单独导入需要写法优雅 产物精确 规避 peer dependency 报错两全其美时的首选需要留意的是无论选择哪种方式都应确保 React 版本不低于 16.8.0并在使用useKeyboardJs、useSpring等特殊 Hook 时在自己的项目中额外安装其所依赖的keyboardjs、react-spring等库。掌握了这套导入体系你就可以放心地在任意工程中按需引入 react-use 的上百个 Hook而无需担心体积失控或依赖缺失。【免费下载链接】react-useReact Hooks — 项目地址: https://gitcode.com/gh_mirrors/re/react-use创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进