开发者问题收集

无效的钩子调用。钩子可以在主体内部调用。我收到此错误

2022-06-07
170
const startTimer = () => {
    Alert.alert('hye timer started')
    useInterval(() => {
      handleTimer()
    }, 1000);
  };

这是我按下按钮时调用的函数。

useInterval 是自定义钩子,其代码如下:

import { useEffect, useRef } from 'react';

export default function useInterval(callback, delay) {
  const savedCallback = useRef();

  // Remember the latest callback.
  useEffect(() => {
    savedCallback.current = callback;
  }, [callback]);

  // Set up the interval.
  useEffect(() => {
    function tick() {
      savedCallback.current();
    }
    if (delay !== null) {
      const id = setInterval(tick, delay);
      return () => clearInterval(id);
    }
  }, [delay]);
}

但是当我按下按钮时,会调用该函数,其中有一个应该被调用的钩子,但它给出了一个错误,即无效的自定义钩子。你能说出这段代码中有什么问题吗?

1个回答

您正尝试访问函数内部的钩子。因此,以下内容无效。

function foo() {
   useSomeHook();
}

钩子只能按 钩子规则 的定义进行调用

[...] from React function components [... and ...] from custom Hooks

函数 startTimer 是常规 Javascript 函数,既不是 React 函数组件也不是自定义钩子。

对于您的特定情况,您可以在钩子本身内定义 startTimer 函数并将其导出。然后,将其称为 onPress

export default function useInterval(callback, delay) {
 const savedCallback = useRef();

  const [start, setStart] = useState(false)

  // Remember the latest callback.
  useEffect(() => {
    savedCallback.current = callback;
  }, [callback]);

  // Set up the interval.
  useEffect(() => {
    if (start) {
      const tick = () => {
          savedCallback.current();
      }
      if (delay !== null) {
        const id = setInterval(tick, delay);
        return () => clearInterval(id);
      }
    }
  }, [delay, start]);

  const startTimer = React.useCallback((shouldStart) => {
    setStart(shouldStart)
  }, []);

  return startTimer;
}

您可以按如下方式启动和停止它:

export default function App() {

  const startTimer = useInterval(() => console.log("callback"), 1000)
  
  return (
    <View style={{margin:50}}>
      <Pressable onPress={() => startTimer(true)}> <Text>Start</Text></Pressable>
      <Pressable onPress={() => startTimer(false)}> <Text>Stop</Text></Pressable>
    </View>
  );
}
David Scholz
2022-06-08