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