在 React 中使用 useEffect() 和 useCallback 获取数据

Data Fetching Using useEffect() And useCallback In React

问题

当在多个地方使用获取功能时,我正在寻找使用 useEffect() 获取数据的最佳方式。

情况

目前,我有一个父组件 (ItemContainer) 和一个子组件 (SearchBar)。 ItemContainer 应该使用 getItemList() 函数获取所有可能的项目列表。我在第一次渲染期间在 useEffect() 中执行这个函数,并将它传递给 SearchBar 组件,这样当用户提交搜索词时,它会更新 itemList 状态通过在 ItemContainer.

中触发 getItemList()

这确实如我所料。但是,我的问题是

  1. 我不太确定在这种情况下在 useEffect() 之外定义 getItemList() 是否可以。根据我一直在阅读的内容(博客文章、react 官方文档),通常建议应该在 useEffect() 中定义数据获取函数,尽管可能存在一些边缘情况。我想知道我的情况是否适用于这种边缘情况。
  2. useCallback中可以将依赖项数组留空吗?我尝试使用 searchTermitemList 填写它,但其中 none 有效 - 我很困惑为什么会这样。

我很遗憾我没有完全理解我写的代码。如果你们中的任何人能告诉我我在这里所缺少的东西,我将不胜感激...

物品容器

    const ItemContainer = () => {
        const [itemList, setItemList] = useState([]);
    
        const getItemList = useCallback( async (searchTerm) => {
            const itemListRes = await Api.getItems(searchTerm);
            setItemList(itemListRes)
        }, []);
    
        useEffect(() => {
            getItemList();
        }, [getItemList]);
    
        return (
            <main>
                <SearchBar search={getItemList} />
                <ItemList itemList={itemList} />
            </main>
        )
    }

搜索栏

const SearchBar = ({ search })  => {
    const [searchTerm, setSearchTerm] = useState('');

    const handleSubmit = (e) => {
        e.preventDefault();
        search(searchTerm);
        setSearchTerm('');
    }

    const handleChange = (e) => {
        setSearchTerm(e.target.value)
    }

    return (
        <form onSubmit={handleSubmit}>
            <input 
                placeholder='Enter search term...'
                value={searchTerm}
                onChange={handleChange}
            />
            <button>Search</button>
        </form>
    )
}

这是我的答案。

  1. 是的,没关系。 useCallback 里面的内容是“冻结”的 可能发生的许多 ItemConteiner 函数调用。自从 useCallback内容只访问setItemList,这也是一个 冻结处理程序,不会有问题。

  2. 这也是正确的,因为空数组意味着“依赖于 什么都没有”。换句话说,回调被创建一次并保持 ItemContainer.

    的一生都被冻结了

相反,这很奇怪:

    useEffect(() => {
        getItemList();
    }, [getItemList]);

有效,但意义不大。 getItemList 只创建一次,那么为什么要根据永远不会改变的东西创建 useEffect

让它更简单,通过 运行 一次:

    useEffect(() => {
        getItemList();
    }, []);