React setState挂钩不适用于useEffect

时间:2019-11-06 13:19:14

标签: javascript reactjs

我有以下代码。这个想法是为模拟组件创建一个简单的加载

const [loading, setLoading] = useState(false)

  function mockLoading () {
    setLoading(true)
    console.log('1', loading)
    setTimeout(() => {
      setLoading(false)
      console.log('2', loading)
    }, 3000)
  }

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

但是由于某些原因,setLoading无法正常工作。 Console.log 1和2均为假

3 个答案:

答案 0 :(得分:4)

handler中声明您的useEffect,然后在外部登录

const [loading, setLoading] = useState(false)

  useEffect(() => {
      function mockLoading () {
         setLoading(true)
         console.log('1', loading)
         setTimeout(() => {
         setLoading(false)
         console.log('2', loading)
       }, 3000)
  }
    mockLoading()
  }, []);

  console.log(loading)

此外,您还应该清洁timeout上的unmount

useEffect(() =>{
    const timeout = setTimeout(() =>{}, 0)

    return clearTimeout(timeout)
},[])

答案 1 :(得分:2)

几件事。一个问题是,当您设置状态时,状态不会立即更新。因此,您的第一个console.log将看到旧状态。不仅如此,而且在调用效果并调用mockLoading时,它将仅看到在调用状态时存在的状态实例。因此,mockLoading永远不会看到对变量的任何更改。这就是为什么效果具有依赖性的原因。这样,当依赖项更新时,您将看到它。但是,我认为在此依赖于代码结构不会对您有所帮助。我的最终目标不是100%明确,但是要根据提交的代码完成所需的工作,您将需要useRef而不是useStateuseRef为您提供了一个始终是当前值的对象。参见:

const loadingRef = useRef(false)

function mockLoading () {
    loadingRef.current = true;
    console.log('1', loadingRef.current)
    setTimeout(() => {
        loadingRef.current = false;
      console.log('2', loadingRef.current)
    }, 3000)
}

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

除非您绝对需要,否则通常不使用引用。尝试在您的loading调用中重构代码,使其对useEffect有依赖性。请记住,如果mockLoading在调用时总是更新loading,则可能会导致无限循环。如果尚未将loading设置为所需的值,请尝试对其进行更新。如果您的最终目标是仅在3秒钟后更新loading,请尝试以下操作:

const [loading,setLoading] = useState(false);

useEffect(() => {
    setTimeout(() => {
        setLoading(true);
    },3000);
},[]);

return <span>{loading ? 'Loading is true!' : 'Loading is false!'}</span>;

如果您想检查加载的值而不渲染它,那么您将需要另一个useEffect并依赖于loading

const [loading,setLoading] = useState(false);

useEffect(() => {
    setTimeout(() => {
        setLoading(true);
    },3000);
},[]);

useEffect(() => {
    console.log(loading);
},[loading]);

return <span>{loading ? 'Loading is true!' : 'Loading is false!'}</span>;

希望这会有所帮助。

答案 2 :(得分:1)

在React中设置状态是异步的,因此在进行更改后,您将不会立即看到状态更改。要跟踪状态更改,您需要使用效果挂钩:

const [loading, setLoading] = useState(false);

function mockLoading() {
  setLoading(true);
  console.log("1", loading);
  setTimeout(() => {
    setLoading(false);
    console.log("2", loading);
  }, 3000);
}

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

// Display the current loading state
useEffect(() => {
  console.log("loading", loading);
}, [loading]);