2022 React 最速上手指南(十一)—— 自定义 hook & 可复用组件

简介: 2022 React 最速上手指南(十一)—— 自定义 hook & 可复用组件

以结果为导向,写给刚学完前端三剑客和想要了解 React 框架的小伙伴,使得他们能快速上手(省略了历史以及一些不必要的介绍)。



自定义 hook


Hooks: functions starting with use — can only be called at the top level of your components or your own Hooks.


虽然 React 自带很多 hook,但肯定不能涵盖我们所有的需求,所以自定义 hook 就很重要了。


我们将 App 组件里【管理 state 并同步到本地存储的功能】抽离出来,创建一个新的自定义 hook 叫做 useSemiPersistentState ,翻译过来就是半持久化,【半】是因为清除浏览器的本地存储就会把应用所有相关数据都删掉。


const useSemiPersistentState = () => {
  const [value, setValue] = React.useState(
    localStorage.getItem("search") || "React"
  );
  React.useEffect(() => {
    localStorage.setItem("value", value);
  }, [value]);
  return [value, setValue];
};
const App = () => {
  ...
  const [searchTerm, setSearchTerm] = useSemiPersistentState();
  ...
};
复制代码


因为我们自定义 hook 的目标是【可复用性】,所以我们要用抽象的值 ”value“,而在 App 组件中调用时可以使用有业务含义的词来命名。


还有一个问题:如果在一个应用中多次调用这个 hook ,由于名字都是 “value”,会造成本地存储的值被覆盖。


可以通过传入一个 key 值解决,同时让它接收一个初始的 state:


const useSemiPersistentState = (key, initialState) => {
  const [value, setValue] = React.useState(
    localStorage.getItem(key) || initialState
  );
  React.useEffect(() => {
    localStorage.setItem(key, value);
  }, [value, key]);
  return [value, setValue];
};
const App = () => {
  ...
  const [searchTerm, setSearchTerm] = useSemiPersistentState(
    "search", "React"
  );
  ...
};
复制代码


因为 key 值来自外部,随时可能发生变化,所以要把它放入 useEffect 的依赖数组里,以防副作用使用了过期的 key 值。


这样我们就创建了第一个自定义 hook,它把复杂的实现细节包装起来,从而使组件逻辑更加清晰,并且可以【复用】到更多的 React 组件中,甚至可以作为第三方库开源出去,比如 streamich/react-usealibaba/hooksvercel/swr 等等。


可复用组件


Computer scientists use abstraction to make models that can be used and re-used without having to re-write all the program code for each new application on every different type of computer.


如果我们同时渲染两个 Search 组件,相同的 htmlFor 和 id 属性值一定会引入 bug,并且由于和搜索功能强相关,使得组件的可复用性非常差。


但该组件实际并不具备任何的 “搜索” 能力,我们可以通过传递 id 和 label 等参数将 Search 组件抽象成一个能覆盖其他搜索场景的通用组件:


const App = () => {
 ....
  return (
    <>
      <InputWithLabel
        id="search"
        label="Search"
        value={searchTerm}
        onInputChange={handleSearch}
      />
      <hr />
      <List list={searchedStories} />
    </>
  );
};
const InputWithLabel = ({ id, label, value, type = "text", onInputChange }) => (
  <>
    <label htmlFor={id}>{label}</label>
    &nbsp;&nbsp;
    <input id={id} type={type} value={value} onChange={onInputChange} />
  </>
);
复制代码


在 InputWithLabel 组件中我们指定了 type 的默认参数,在没有值或 undefined 被传入时会使用默认参数

目录
相关文章
|
前端开发 JavaScript API
探究 React Hooks:如何利用全新 API 优化组件逻辑复用与状态管理
本文深入探讨React Hooks的使用方法,通过全新API优化组件逻辑复用和状态管理,提升开发效率和代码可维护性。
|
存储 前端开发 JavaScript
React Hooks的魔法:如何在组件世界里施展响应式与复用的魔法
【8月更文挑战第27天】React Hooks 是自 React 16.8 起新增的功能,支持开发者在无需类组件的情况下利用 React 的状态管理和特性。本文通过实例展示了多种核心 Hooks 的使用方法:`useState` 用于实现响应式状态管理;`useEffect` 处理副作用操作,如数据获取等;`useMemo` 和 `useCallback` 有助于性能优化;`useRef` 则提供对 DOM 的直接引用。
240 2
|
前端开发
React useImperativeHandle Hook
【7月更文挑战第1天】React useImperativeHandle Hook
191 3
|
前端开发 JavaScript 数据格式
react18【系列实用教程】Hooks (useState,useReducer,useRef,useEffect,useContext,useMemo,useCallback,自定义 Hook )
react18【系列实用教程】Hooks (useState,useReducer,useRef,useEffect,useContext,useMemo,useCallback,自定义 Hook )
628 1
|
前端开发
React 中的 Hook 概念
【8月更文挑战第31天】
364 0
|
前端开发
Vue3 【仿 react 的 hook】封装 useTitle
Vue3 【仿 react 的 hook】封装 useTitle
262 0
|
前端开发 API
Vue3 【仿 react 的 hook】封装 useLocation
Vue3 【仿 react 的 hook】封装 useLocation
251 0
|
存储 前端开发 中间件
React组件间的通信
React组件间的通信
245 1
|
前端开发 JavaScript
【边做边学】React Hooks (二)——useEffect Hook
【边做边学】React Hooks (二)——useEffect Hook
196 0
|
前端开发 JavaScript
详解React:Props构建可复用UI的基石
详解React:Props构建可复用UI的基石
213 0