我创建了一个自定义钩子,用于监视滚动行为。但是,当我从使用该挂钩的组件中更改状态时,确实从控制台日志中看到了状态更改,但是一旦开始滚动,该状态的原始值为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;
我更新了功能。即使在Example.js中的第一个useEffect中更改了状态,setInterval函数也始终返回true。 React dev tools console log
更新,如果我将其更改为此,它将起作用,我认为问题与事件侦听器的状态范围有关。需要将其删除并以正确的状态进行更新。
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;
答案 0 :(得分:0)
您没有在示例中正确导出函数,但是将其导入父组件,在子组件上使用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;