React Hooks:UseEffect、UseCallback、UseMemo UseEffect useEffect 示例 UseMemo UseCallback 进一步阅读

2025-05-27

React Hooks:UseEffect、UseCallback、UseMemo

使用效果

useEffect 示例

使用备忘录

使用回调

进一步阅读

React 自带了一大堆 Hooks,如果一次性学习它们,可能会有点难以掌握。这篇文章应该能帮助你理解其中三个 Hooks 的区别和用例。

使用效果

纯组件仅与其自身及其子组件交互。任何时候你需要与组件外部的世界交互,你都会处理副作用

React 为我们提供了一个方便的钩子来处理这些问题。该React.useEffect钩子让我们指定一个处理外力的函数,提供第二个函数来清理它,并删除依赖项列表,以便我们可以在其中一个依赖项发生变化时重新运行效果。

useEffect 示例

更新页面标题

此效果将在第一次渲染组件时运行,并且只有在标题发生变化时才会再次运行。

const [title, setTitle] = React.useState("Hooks 101");

React.useEffect(() => {
    document.title = title;
}, [title]);
Enter fullscreen mode Exit fullscreen mode

从 API 获取数据并放入本地状态。

由于我们的状态变化不会影响返回的产品列表,我们可以传递一个空数组[]作为我们的依赖项,以便效果仅在首次安装组件时运行。

const [products, setProducts] = React.useState([]);

React.useEffect(() => {
    getProducts()
    .then(products => {
        setProducts(products);
    })
}, []);
Enter fullscreen mode Exit fullscreen mode

根据查询,从 API 获取数据并放入本地状态。

如果我们有一个查询或过滤器来修改我们想要的 API 数据集,那么我们可以将其作为依赖项传递,以确保 React 每次使用新查询渲染组件时都运行此效果。

const [products, setProducts] = React.useState([]);
const [query, setQuery] = React.useState("");

React.useEffect(() => {
    getProducts({name: query})
    .then(products => {
        setProducts(products);
    })
}, [query]);
Enter fullscreen mode Exit fullscreen mode

调度 Redux 动作。

如果您的 GET 操作已经减少到您的 Redux 状态,那么您不需要在本地维护任何内容。

通过作为依赖项传递products.length,您只需运行此

const dispatch = Redux.useDispatch();
const products = Redux.useSelector(state => state.products);

React.useEffect(() => {
    dispatch(GetProducts())
}, []);
Enter fullscreen mode Exit fullscreen mode

使用备忘录

与 useEffect 不同,React.useMemo每次更改其依赖项之一时不会触发。

记忆函数会首先检查依赖项自上次渲染以来是否发生了变化。如果是,则执行该函数并返回结果。如果否,则直接返回上次执行的缓存结果。

这对于昂贵的操作非常有用,例如转换 API 数据或进行您不想不必要地重新进行的重大计算

useMemo 示例

const posts = Redux.useSelector(state => state.posts);

const tags = React.useMemo(() => {
    return getTagsFromPosts(posts)
}, [posts]);
Enter fullscreen mode Exit fullscreen mode

使用回调

这是记忆函数的一个特例。由于 JavaScript 通过引用比较相等性,因此组件首次渲染时创建的函数将与后续渲染时创建的函数不同。

如果你尝试将函数作为 props 或 state 传递,这意味着每次都会将其视为 props 更改。通过将其包装在 useCallback 中,React 会知道它是同一个函数。你仍然可以添加依赖项数组,以便在依赖项发生变化时触发重新计算。

这里有一个强有力的用例,可以避免子组件重新渲染

useCallback 示例

每次此组件渲染时,它还会触发整个 Button 组件的重新渲染,因为removeFromCart每次函数都是唯一的。

const dispatch = useDispatch();

const removeFromCart = () => dispatch(removeItem(product.id));

return (
    <Button onClick={removeFromCart}>Delete</Button>
);
Enter fullscreen mode Exit fullscreen mode

用这个替换我们的回调函数可以完全避免这个问题。现在,按钮只会在产品 ID 发生变化时重新渲染,这样它就能从购物车中移除新产品了。

const removeFromCart = React.useCallback(() => {
    dispatch(removeItem(product.id))
}, [product.id]);
Enter fullscreen mode Exit fullscreen mode

进一步阅读

https://overreacted.io/a-complete-guide-to-useeffect/

https://medium.com/@vcarl/everything-you-need-to-know-about-react-hooks-8f680dfd4349

https://kentcdodds.com/blog/usememo-and-usecallback

https://www.robinwieruch.de/react-hooks-fetch-data/

https://stackoverflow.com/questions/54371244/what-is-the-intention-of-using-reacts-usecallback-hook-in-place-of-useeffect

https://stackoverflow.com/questions/54963248/whats-the-difference-between-usecallback-and-usememo-in-practice/54965033#54965033

文章来源:https://dev.to/devcord/react-hooks-useeffect-usecallback-usememo-3o42
PREV
7 个无人谈论的免费 API
NEXT
第 2 部分:使用 OhMyZSH + VSCode 🔥⚡️🔥 插件、字体、图标等让你的开发环境更棒