我创建了一个监控滚动行为的自定义挂钩。但是,当我更改使用钩子的组件的状态时,我确实会从控制台日志中看到状态的更改,但一旦我开始滚动,状态的原始值为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;
import React, { useState, useEffect } from 'react';
const useExample = () => {
const [status, setStatus] = useState(true);
console.log(`useExample status: ${status}`);
useEffect(() => {
window.addEventListener('scroll', handleScroll);
return () => window.removeEventListener('scroll', handleScroll);
}, []);
function handleScroll() {
console.log(`handle scroll, status: ${status}`);
}
return [status, setStatus];
};
export default useExample;
我更新了功能。setInterval函数始终返回true,即使状态在Example.js中的第一个useEffect中发生了更改。React开发工具控制台日志
更新如果我把它改成这个,我相信这个问题与事件侦听器的状态范围有关。它需要删除并更新为正确的状态。
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;