首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >自定义钩子问题-无限依赖循环

自定义钩子问题-无限依赖循环
EN

Stack Overflow用户
提问于 2019-08-31 15:09:47
回答 2查看 363关注 0票数 1

我一直喜欢进入钩子和处理所有新的有趣的问题,提出了现实世界的问题:)这里有一个我遇到过几次,并想看看你如何“应该”解决它!

概述:我创建了一个自定义钩子来封装我的应用程序的一些业务逻辑,并存储我的一些状态。我使用组件内部的自定义钩子,并在加载时触发事件。

问题是:我的钩子的loadItems函数需要访问我的items才能获取最后一项的ID。将items添加到我的依赖项数组将导致无限循环。下面是一个(简化的)示例:

ItemList 简单组件

代码语言:javascript
运行
复制
//
// Simple functional component
//

import React, { useEffect } from 'react'
import useItems from '/path/to/custom/hooks/useItems'

const ItemList = () => {
    const { items, loadItems } = useItems()

    // On load, use our custom hook to fire off an API call
    // NOTE: This is where the problem lies. Since in our hook (below)
    // we rely on `items` to set some params for our API, when items changes
    // `loadItems` will also change, firing off this `useEffect` call again.. and again :)
    useEffect(() => {
        loadItems()
    }, [loadItems])

    return (
        <ul>
            {items.map(item => <li>{item.text}</li>)}
        </ul>
    )
}

export default ItemList

useItems 定制 Hook

代码语言:javascript
运行
复制
//
// Simple custom hook
//

import { useState, useCallback } from 'react'

const useItems = () => {
    const [items, setItems] = useState([])

    // NOTE: Part two of where the problem comes into play. Since I'm using `items`
    // to grab the last item's id, I need to supply that as a dependency to the `loadItems`
    // call per linting (and React docs) instructions. But of course, I'm setting items in
    // this... so every time this is run it will also update.
    const loadItems = useCallback(() => {
        // Grab our last item
        const lastItem = items[items.length - 1]
        // Supply that item's id to our API so we can paginate
        const params = {
            itemsAfter: lastItem ? lastItem.id : nil
        }
        // Now hit our API and update our items
        return Api.fetchItems(params).then(response => setItems(response.data))
    }, [items])

    return { items, loadItems }
}

export default useItems

代码中的注释应该指出问题所在,但我现在想出的唯一解决方案是为loadItems调用(ex )提供params,以使指针感到高兴。loadItems({ itemsAfter: ... })),因为数据已经在这个自定义钩子中,所以我真的希望不必在任何地方使用loadItems函数。

任何帮助都是非常感谢的!

麦克

EN

回答 2

Stack Overflow用户

发布于 2019-08-31 15:12:49

如果计划只运行一次效果,则忽略所有依赖项:

代码语言:javascript
运行
复制
 useEffect(() => {
    loadItems();
 }, []);
票数 1
EN

Stack Overflow用户

发布于 2019-08-31 17:12:07

您可以尝试使用useReducer,将分派作为loadItems传递,因为它从不更改引用。还原器只关心操作是否为NONE,因为这是useEffect的清理功能用来清理的。

如果操作不是“无”,则状态将被设置为“项的最后一项”,这将触发useEffect使用您的api获取,并且在解决时将使用setItems来设置项。

代码语言:javascript
运行
复制
const NONE = {};
const useItems = () => {
  const [items, setItems] = useState([]);
  const [lastItem, dispatch] = useReducer(
    (state, action) => {
      return action === NONE
        ? NONE
        : items[items.length - 1];
    },
    NONE
  );

  useEffect(() => {
    //initial useEffect or after cleanup, do nothing
    if (lastItem === NONE) {
      return;
    }
    const params = {
      itemsAfter: lastItem ? lastItem.id : Nil,
    };
    // Now hit our API and update our items
    Api.fetchItems(params).then(response =>
      setItems(response)
    );
    return () => dispatch(NONE); //clean up
  }, [lastItem]);
  //return dispatch as load items, it'll set lastItem and trigger
  // the useEffect
  return { items, loadItems: dispatch };
};
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57739169

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档