发布于 2026-01-06 1 阅读
0

React Hooks:UseEffect、UseMemo、UseCallback UseEffect UseEffect 示例 UseMemo UseCallback 延伸阅读

React Hooks:UseEffect、UseMemo、UseCallback

使用效果

使用效果示例

使用备忘录

使用回调

延伸阅读

React 自带很多 Hook,如果一下子全部学习可能会有点难掌握。这篇文章将帮助你理解其中三个 Hook 的区别和使用场景。

使用效果

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

React 提供了一个方便的 hook 来处理这些问题。这个React.useEffecthook 允许我们指定一个处理外部因素的函数,提供一个后续清理函数,并列出依赖项列表,以便在某个依赖项发生变化时重新运行 effect。

使用效果示例

更新页面标题

该效果将在组件首次渲染时运行,之后只有在标题更改时才会再次运行。

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 action。

如果你的 GET 操作已经将 Redux 状态转换为 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 数据或进行大量计算等耗时操作非常有用,可以避免不必要的重复计算。

使用示例备忘录

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

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

使用回调

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

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

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

使用回调的示例

每次渲染此组件时,都会触发 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/jacobmparis/react-hooks-useeffect-usememo-usecallback-41ol