学习React 18需要了解的新Hook


1. useDeferredValue

useDeferredValue是一个非常有用的hook,它可以用来推迟某个值的更新,以提高性能。它在处理用户输入或其他频繁变化的值时特别有用。通过将某个值包装在useDeferredValue中,React会推迟该值的更新,直到浏览器处于空闲状态。

import { useDeferredValue, useState } from 'react';

const SlowUI = () => (
  <>
    {Array(50000)
      .fill(1)
      .map((_, index) => (
        <span key={index}>{100000} </span>
      ))}
  </>

);

function App({
  const [value, setValue] = useState(0);
  const deferredValue = useDeferredValue(value);

  const handleClick = () => {
    setValue(value + 1);
  };

  return (
    <>
      <button onClick={handleClick}>{value}</button>
      <div>DeferredValue: {deferredValue}</div>
      <div>
        <SlowUI />
      </div>
    </>

  );
}

export default App;

2. useTransition

useTransition()是一个用于过渡效果的hook。它返回过渡的状态和一个用于启动过渡的函数。

const [isPending, startTransition] = useTransition();

React状态更新可以分为两类:

紧急更新 – 反映直接的交互,例如键入、点击、按下、拖动等。过渡更新 – 用于将UI从一个视图过渡到另一个视图。在过渡中,更新会让位给更紧急的更新。下面是一个示例,将useTransition放置在src/App.js中:

import React, { useState, useTransition } from 'react';

function App({
  const [isPending, startTransition] = useTransition();
  const [text, setText] = useState('');

  const handleChange = (event) => {
    startTransition(() => {
      setText(event.target.value);
    });
  };

  return (
    <div>
      <input type="text" value={text} onChange={handleChange} />
      {isPending ? <p>Loading...</p> : <p>Text: {text}</p>}
    </div>

  );
}

export default App;

在上述代码中,我们使用useTransition() hook来获取过渡的状态和startTransition()函数。我们还使用useState() hook来创建一个文本输入框的状态和更新函数。在handleChange函数中,我们使用startTransition()函数将文本更新操作包裹起来,以确保它在过渡期间能够让位给更紧急的更新。当isPending为true时,显示”Loading…”,否则显示文本的内容。

3. useMutableSource

useMutableSource是一个高级的hook,它可以用来创建可变的数据源,以便在自定义的React Hooks中共享数据。它可以用来解决一些复杂的状态共享问题。

import { useMutableSource } from 'react';

function useCustomHook({
  const mutableSource = useMutableSource(myMutableSource, getSnapshot, subscribe);

  // 使用mutableSource进行状态管理和更新

  return mutableSource;
}

4. useId

在Web应用程序中,有些情况下需要使用唯一的ID,例如:

<label for="ID">,其中for属性必须与相关元素的id属性相等,以将它们绑定在一起。aria-labelledby,其中aria-labelledby属性可以接受多个ID。useId()是一个生成唯一ID的hook:

这个ID在服务器和客户端之间是稳定的,避免了服务器端渲染时的混合问题。这个ID在整个应用程序中是唯一的。对于多根应用程序,createRoot/hydrateRoot有一个可选的identifierPrefix属性,可以用于添加前缀以防止冲突。这个ID可以附加前缀和/或后缀,以生成在组件中使用的多个唯一ID。这似乎是一个微不足道的功能。但是,useId是从useOpaqueIdentifier演变而来的,后者生成的是不可操作的不透明ID。

使用useId可以帮助我们生成唯一的ID,确保在应用程序中的各个组件中使用不重复的ID。这对于构建可靠的用户界面和确保无障碍性非常重要。

请注意,useId是一个自定义hook,并不是React的内置hook,你可以根据自己的需求实现它或使用现有的库,如下使用:

import { useId } from 'react';

const Comp1 = () => {
  const id = useId();
  return <div>Comp1 id({id})</div>;
};

const Comp2 = () => {
  const id = useId();
  return (
    <>
      <div>Comp2 id({id})</div>
      <label htmlFor={`${id}-1`}>Label 1</label>
      <div>
        <input id={`${id}-1`} type="text" />
      </div>
      <label htmlFor={`${id}-2`}>Label 2</label>
      <div>
        <input id={`${id}-2`} type="text" />
      </div>
    </>

  );
};

const Comp3 = () => {
  const id = useId();
  return (
    <>
      <div>Comp3 id({id})</div>
      <div aria-labelledby={`${id}-a ${id}-b ${id}-c`}>I am Comp3</div>
    </>

  );
};

function App({
  return (
    <>
      <Comp1 />
      <Comp2 />
      <Comp3 />
    </>

  );
}

export default App;

5. useSyncExternalStore

useSyncExternalStore是一个推荐用于从外部数据源(存储)中读取和订阅数据的hook。

下面是该hook的函数签名:

const state = useSyncExternalStore(subscribe, getSnapshot[, getServerSnapshot]);

该方法接受三个参数:

subscribe:一个函数,用于注册一个回调函数,该回调函数在存储更改时被调用。getSnapshot:一个函数,返回存储的当前值。getServerSnapshot:一个函数,返回在服务器渲染期间使用的快照。这是一个可选参数。该方法返回存储的值,即state

如下代码:

import { useSyncExternalStore } from 'react';

function App({
  const width = useSyncExternalStore(
    (listener) => {
      window.addEventListener('resize', listener);
      return () => {
        window.removeEventListener('resize', listener);
      };
    },
    () => window.innerWidth
    // () => -1,
  );

  return <p>Size: {width}</p>;
}

export default App;

在上述代码中,调用了useSyncExternalStore

subscribe:它为窗口调整大小事件监听器注册了一个回调函数。getSnapshot:它返回当前浏览器窗口的宽度。getServerSnapshot:这是用于服务器渲染的,但在此处不需要,可以简单地返回-1。

6. useInsertionEffect

useInsertionEffect是在React 18中引入的一个新的hook。它具有与useEffect相同的签名,但在所有DOM变化之前同步触发。也就是说,它在useLayoutEffect之前触发。它用于在读取布局之前向DOM插入样式。

useInsertionEffect主要用于CSS-in-JS库,例如styled-components。由于此hook的范围有限,它无法访问refs并且无法调度更新。

以下示例比较了useEffectuseLayoutEffectuseInsertionEffect

import { useEffect, useLayoutEffect, useInsertionEffect } from 'react';

function App({
  useEffect(() => {
    console.log('useEffect');
    return () => {
      console.log('Cleanup useEffect');
    };
  }, []);

  useLayoutEffect(() => {
    console.log('useLayoutEffect');
    return () => {
      console.log('Cleanup useLayoutEffect');
    };
  }, []);

  useInsertionEffect(() => {
    console.log('useInsertionEffect');
    return () => {
      console.log('Cleanup useInsertionEffect');
    };
  }, []);

  return <div>Hello World</div>;
}

export default App;

在上述代码中,我们使用了三个不同的effect hook:useEffectuseLayoutEffectuseInsertionEffect。每个effect hook都输出一条消息,并在组件卸载时进行清理。

当我们运行这个示例时,我们可以观察到它们的触发顺序和清理顺序。useEffect在组件渲染后触发,useLayoutEffect在DOM变化之后触发,而useInsertionEffect在DOM变化之前触发。

请注意,useInsertionEffect是React 18中新增的一个hook,并且在特定的使用场景下才会使用。通常情况下,使用useEffectuseLayoutEffect就足够满足大多数需求。

7. useSyncExternalState

useSyncExternalState是一个用于同步外部状态的hook,在React 18中引入了对外部状态同步的原生支持。它可以用来将React组件的状态与外部的状态进行同步。

import { useSyncExternalState } from 'react';

function MyComponent({
  const [count, setCount] = useState(0);

  // 将外部状态与组件状态同步
  useSyncExternalState(count, setCount);

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
      <button onClick={() => setCount(count - 1)}>Decrement</button>
    </div>

  );
}

在上述代码中,我们使用useSyncExternalState将组件的count状态与外部的状态进行同步。这样,当外部的状态发生变化时,组件的状态也会相应地更新。

8. useErrorHandler

useErrorHandler是一个用于处理错误的hook,在React 18中引入了对错误处理的原生支持。它可以用来捕获和处理组件中发生的错误。

import { useErrorHandler } from 'react';

function MyComponent({
  const handleError = useErrorHandler();

  const fetchData = async () => {
    try {
      const response = await fetch('api/data');
      const data = await response.json();
      // 处理获取的数据
    } catch (error) {
      handleError(error);
    }
  };

  return (
    <div>
      <button onClick={fetchData}>Fetch Data</button>
    </div>

  );
}

在上述代码中,我们使用useErrorHandler来获取一个错误处理函数,并在fetchData函数中捕获和处理错误。这样,当发生错误时,我们可以通过错误处理函数来进行相应的处理。

以上就是今日分享的文章,在写文章的时候,看到弹出的消息:歌手李玟因为抑郁症轻生了,唉,其实很多事情看开一点就好了。希望看到文文的小伙伴们每天都开开心心,晚安啦!!



原文始发于微信公众号(大前端编程教学):学习React 18需要了解的新Hook

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/224016.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!