如何在React Hooks中使用效果一次,但仍然使用状态?

时间:2019-05-07 19:56:21

标签: reactjs react-hooks

我试图仅在安装/卸载时设置一个间隔,但是允许回调从状态中获取一个变量。

我有这样的代码:

const [cachedData, setCachedData] = useState(false);

async function refreshData() {
  const data = await axios('http://www.example.com/');
  setCachedData(data);
}

useEffect(() => {
  let interval;
  async function fetch() {
    await refreshData();
    interval = setInterval(refreshData,5000);
    console.log('set interval to', interval)
  }

  fetch();

  return () => {
    console.log('clearing interval', interval);
    clearInterval(interval);
  }
}, []);

我遇到了22个问题。 useEffect的第二个参数指出要注意哪些变量。我读过使其成为一个空数组,使得它只能安装/卸载,而不是进行任何状态更新。我发现的问题是,这样做意味着refreshData无法访问cachedData,所以我不知道我有有效的数据(避免在一段时间内避免XHR请求)。如果我将cachedData传递到useEffect的第二个参数中,它将具有该变量,但运行得比预期的多。不确定是否可以解决此问题。

我应该注意,如果我将cachedData传递给第二个arg,并且将console.log传递给间隔的清除和设置,则我的控制台将输出如下内容:

clearing interval undefined
set interval to 5
set interval to 7

因此,它似乎运行了卸载,然后效果重复了两次,而无需再次清除。这会导致两次axios呼叫。

1 个答案:

答案 0 :(得分:1)

您可以使用ref来获取当前的cachedData,如下所示:

const [cachedData, setCachedData] = useState(false);
const cachedDataRef = useRef(cachedData);

useEffect(() => {
  // Update ref in effect so that render has no side effects.
  cachedDataRef.current = cachedData;
}, [cachedData]);

useEffect(() => {

  async function refreshData() {
    if (cachedDataRef.current) {
      // do something different
    } else {
      const data = await axios('http://www.example.com/');
      setCachedData(data);
    }
  }
  let interval;
  async function fetch() {
    await refreshData();
    interval = setInterval(refreshData,5000);
    console.log('set interval to', interval)
  }

  fetch();

  return () => {
    console.log('clearing interval', interval);
    clearInterval(interval);
  }
}, []);