Reactjs 反应挂钩状态不匹配

Reactjs 反应挂钩状态不匹配,reactjs,react-hooks,use-state,Reactjs,React Hooks,Use State,我创建了一个监视滚动行为的自定义钩子。但是当我从使用钩子的组件更改状态时,我确实从控制台日志中看到状态更改,但是一旦我开始滚动,状态的原始值为true。更奇怪的是,react dev工具与控制台日志输出不匹配 import React, { useEffect } from 'react'; import useExample from './useExample'; function Example() { const [status, setStatus] = useExample(

我创建了一个监视滚动行为的自定义钩子。但是当我从使用钩子的组件更改状态时,我确实从控制台日志中看到状态更改,但是一旦我开始滚动,状态的原始值为true。更奇怪的是,react dev工具与控制台日志输出不匹配

import React, { useEffect } from 'react';
import useExample from './useExample';


function Example() {
  const [status, setStatus] = useExample();
  console.log(`example, status: ${status}`);


  useEffect(() => {
    setStatus(false);
  },[]);

  useEffect(() => {
    setInterval(() => console.log(status), 2000);
  }, [])

  return (<div>
    Something scrollable
    ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
    ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
    ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
    ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
    ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
    ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
    ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
    ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
    ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
  </div>);

}

export default Example;
我更新了函数。setInterval函数始终返回true,即使在Example.js中的第一个useffect中更改了状态。

更新它可以工作如果我将其更改为此,我相信问题与事件侦听器的状态范围有关。需要将其删除并更新为正确的状态

import React, { useState, useEffect, useCa } from 'react';

const useExample = () => {
  const [status, setStatus] = useState(true);
  console.log(`useExample status: ${status}`);
  useEffect(() => {
    window.addEventListener('scroll', handleScroll);
    return () => window.removeEventListener('scroll', handleScroll);
  }, [status]);

  useEffect(() => {
    console.log(`${status} useffect`);
  }, [status]);

  function handleScroll() {
    console.log(`handle scroll, status: ${status}`);
  }

  return [status, setStatus];
};

export default useExample;

在示例中,您没有正确导出函数,但在父组件上导入它们,在子组件上使用useState,如果要将函数作为子组件分离,则状态应在父组件中,并在子组件中导入,其中您的状态最初设置为true,您的useExample将始终返回true

export const useExample = (status) => {

  console.log(`useExample status: ${status}`);

  function handleScroll() {
    console.log(`handle scroll, status: ${status}`);
  }

  useEffect(() => {
     window.addEventListener('scroll', handleScroll);
     return () => window.removeEventListener('scroll', handleScroll);
  }, []);

};
而在父代中,它应该是

import {useExample} from './useExample';

useExample(status);
但是,由于函数中的内容是useEffect,因此您可以在父组件中这样编写它。这样做比较容易

import React, { useState, useEffect } from 'react';

function Example() {
   const [status, setStatus] = useState(true);


   function handleScroll() {
     console.log(`handle scroll, status: ${status}`);
   }

   useEffect(() => {
     window.addEventListener('scroll', handleScroll);
     return () => window.removeEventListener('scroll', handleScroll);
   }, []);


   useEffect(() => {
     setStatus(false);
   },[]);

   useEffect(() => {
     setInterval(() => console.log(status), 2000);
   }, [])

   return (<div>
     Something scrollable
      ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
      ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
      ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
      ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
      ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
      ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
      ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
      ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
      ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
   </div>);

}

export default Example;
import React,{useState,useffect}来自“React”;
函数示例(){
const[status,setStatus]=使用状态(true);
函数handleScroll(){
log(`handle scroll,status:${status}`);
}
useffect(()=>{
window.addEventListener('scroll',handleScroll);
return()=>window.removeEventListener('scroll',handleScroll);
}, []);
useffect(()=>{
设置状态(假);
},[]);
useffect(()=>{
setInterval(()=>console.log(状态),2000);
}, [])
返回(
可滚动的东西
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
);
}
导出默认示例;

但是我从UseExample返回[status,setStatus]而不是{status,setStatus}我更新了我的答案,检查这是否有效。我还没有测试它,嗯,不确定,所以我看到了问题,我正在使用事件监听器,如果使用钩子,需要重新安装,还试图恢复滚动逻辑,所以我需要它在一个单独的钩子中。为什么你要在另一个组件而不是在同一个组件中编写事件监听器。需要重用该组件吗
import React, { useState, useEffect } from 'react';

function Example() {
   const [status, setStatus] = useState(true);


   function handleScroll() {
     console.log(`handle scroll, status: ${status}`);
   }

   useEffect(() => {
     window.addEventListener('scroll', handleScroll);
     return () => window.removeEventListener('scroll', handleScroll);
   }, []);


   useEffect(() => {
     setStatus(false);
   },[]);

   useEffect(() => {
     setInterval(() => console.log(status), 2000);
   }, [])

   return (<div>
     Something scrollable
      ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
      ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
      ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
      ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
      ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
      ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
      ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
      ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
      ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
   </div>);

}

export default Example;