Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/390.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 反应:如何优化共享数据的自定义挂钩?_Javascript_Reactjs_Request_Axios - Fatal编程技术网

Javascript 反应:如何优化共享数据的自定义挂钩?

Javascript 反应:如何优化共享数据的自定义挂钩?,javascript,reactjs,request,axios,Javascript,Reactjs,Request,Axios,我有一个与以下类似的自定义挂钩: import { useEffect, useState } from 'react'; import axios from 'axios'; const myCustomHook = () => { const [countries, setCountries] = useState([]); const [isLoading, setLoading] = useState(true); useEffect(() => {

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

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;

一个解决方案是引入一个定制的“缓存层”(在钩子和axios请求之间),该层:

  • 缓存从第一个成功请求返回的
    coutries
    数据
  • 在后续请求中返回相同的缓存数据
  • 有多种方法可以实现这一点-一种可能是定义一个
    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;
    }
    
    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;
    
    myCustomHook.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;
    }
    
    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;
    

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

    即使第一个实例的状态已填充了
    国家/地区
    ,第二个实例仍不知道它,并且仍然为空


    您可以将
    国家
    作为道具消费,如果为空则调用效果,否则只需从道具返回
    国家

    我不喜欢那种百分之百的解决方案。我觉得很奇怪,组件或钩子更改了不在其作用域内的变量。但我想不出比这更好的办法来解决这个问题了。谢谢。我投票结束这个问题,因为它属于我的。