【问题标题】:React: How optimize a custom hook that shares data?React:如何优化共享数据的自定义钩子?
【发布时间】:2019-10-09 23:02:56
【问题描述】:

我有一个与以下类似的自定义 Hook:

import { useEffect, useState } from 'react';

import axios from 'axios';

const myCustomHook = () => {
  const [countries, setCountries] = useState([]);
  const [isLoading, setLoading] = useState(true);

  useEffect(() => {
      (async () =>
        await axios
          .get("MY_API/countries")
          .then(response => setCountries(response.data))
          .finally(() => setLoading(false)))();
  }, []);

  return countries;
};

export default myCustomHook;

钩子效果很好,但我在我的应用程序的三个不同领域使用它,尽管使用钩子的所有国家都是相同的。

有没有很好的模式来调用 axios 请求一次而不是三次?

编辑 - 解决后的最终代码

import { useEffect, useState } from 'react';

import axios from 'axios';

let fakeCache = {
    alreadyCalled: false,
    countries: []
};

const myCustomHook = (forceUpdate = false) => {
  const [isLoading, setLoading] = useState(true);

  if (!fakeCache.alreadyCalled || forceUpdate) {
      fakeCache.alreadyCalled = true;

      (async () =>
        await axios
          .get("MY_API/countries")
          .then(response => setCountries(response.data))
          .finally(() => setLoading(false)))();
  }

  return countries;
};

export default myCustomHook;

【问题讨论】:

  • 我投票结束这个问题,因为它属于Code Review

标签: javascript reactjs request axios


【解决方案1】:

对此的一种解决方案是引入一个自定义“缓存层”(在您的钩子和 axios 请求之间):

  1. 缓存第一个成功请求返回的coutries数据,
  2. 在后续请求中返回相同的缓存数据

这可以通过多种方式实现 - 一种可能性是定义一个 getCountries() 函数,该函数在单独的模块中实现该缓存逻辑,然后从您的钩子中调用该函数:

countries.js

import axios from 'axios';

// Module scoped variable that holds caches data
let cachedData = undefined;

// Example function wraps network request with caching layer
export const getCountries = async() => {

  // We expect the data for countries to be an array. If cachedData
  // is not an array, attempt to populate the cache with data
  if (!Array.isArray(cachedData)) {  
    const response = await axios.get("MY_API/countries");

    // Populate the cache with data returned from request
    cachedData = response.data;
  }

  return cachedData;
}

myCustomHook.js

import { useEffect, useState } from 'react';
import { getCountries } from "/countries";

const myCustomHook = () => {
  const [countries, setCountries] = useState([]);
  const [isLoading, setLoading] = useState(true);

  useEffect(() => {

    (async() => {
      try {       
        setLoading(true);

        // Update hooks state with countries data (cached or fresh)
        setCountries(await getCountries());

      } finally {
        setLoading(false)
      }
    }, []);
  });
}
export default myCustomHook;

【讨论】:

  • 我 100% 不喜欢那个解决方案。对我来说很奇怪,组件或钩子更改了不在其范围内的变量。但我想不出更好的办法来解决这个问题。谢谢。
【解决方案2】:

组件的每个实例彼此独立运行。

即使第一个实例状态有 countries 填充,第二个实例也不知道它并且仍然是空的。

您可以改为使用 countries 作为道具,如果为空则调用效果,否则只需从道具返回 countries

【讨论】:

    猜你喜欢
    • 2019-09-19
    • 2020-08-09
    • 1970-01-01
    • 2022-01-10
    • 2022-01-07
    • 1970-01-01
    • 2021-03-18
    • 2020-08-15
    • 1970-01-01
    相关资源
    最近更新 更多