392 - 《MDH Weekly 2023 回顾(1)- React Part 1》

发布于 2023年12月25日

年底了,做下 MDH Weekly 一年的文章回顾。我把今年周刊里的文章重新理了一遍,删选了觉得目前看仍旧有价值的文章,做了下分类并重新翻了一遍。以下是 React 的部分。

1、ref 属性除了和 useRef 结合使用外,容易忽略的是他还可以作为 callback 使用,比如 <div ref={(el) => {}} />,其在 DOM 元素创建和删除时被调用,删除时传入 null。一些应用场景包括,1)DOM 元素挂载时滚动到该元素,比如 <li ref={isLast ? scrollTo : undefined} />,2)测量 DOM 元素尺寸,比如 <div ref={measureRef} />,3)Modal + createPortal 创建模态窗,<div ref={setModalElement} />。详见 https://julesblom.com/writing/ref-callback-use-cases#4-share-the-dom-ref

2、关于受控和不受控。1)简单说,就是「是否受控」即「表单元素的值是否由 React 控制」,2)一个注意点,受控的初始值如果为空,要给空字符串而不要给 undefined,比如 const [val, setVal] = useState(),val 为 undefined 会让表单元素变成不受控,3)当需要唯一 id 时,比如用于可访问性和可用性的 htmlFor,可以用 useId() 生成,好处是 SSR 友好、多实例友好、re-render 稳定等。详见 https://www.joshwcomeau.com/react/data-binding/

3、如何在 React 中实现 debounce,代码如下。如果你手写 debounce,可能会遇到几个坑,1)如果只有 delay 效果而没有 debounce 效果,那通常是因为 debounce() 每次 re-render 时都被调用了,而 debounce() 理论上只应该被调一次,所以用 useMemo() + 空依赖以避免重复执行,2)如果 callback 里取 React 的 state 或 props,始终是初始值,那说明 callback 没有在 re-render 时被刷新,那需要用 useRef + useEffect,当 callback 更新时刷新 ref。详见 https://www.developerway.com/posts/debouncing-in-react

const useDebounce = (callback) => {
  const ref = useRef();
  useEffect(() => {
    ref.current = callback;
  }, [callback]);
  const debouncedCallback = useMemo(() => {
    const func = () => {
      ref.current?.();
    };
    return debounce(func, 1000);
  }, []);
  return debouncedCallback;
};

4、关于错误处理。直接 try…catch 会有不少限制,但使用 React 官方的 ErrorBoundary 也有不少限制。这个限制是,React生命周期之外的错误不捕获,比如 resolved promises, async code with setTimeout, various callbacks and event handlers。怎么解?dan 给了个 Hack 方案,简单说就是 try {} catch(e) { setState(() => throw e) }。基于此,我们可以稍微封装下,比如 useThrowAsyncErroruseCallbackWithErrorHandling,这样就不需要每次声明一个新的 setState 了。同时也可以考虑用 bvaughn/react-error-boundary 。详见 https://www.developerway.com/posts/how-to-handle-errors-in

内容预览已结束

此内容需要会员权限。请先登录以查看完整内容。