ooo*_*ooo 7 javascript reactjs
我正在尝试学习反应钩子。我需要帮助来理解 react 函数是否总是在每次渲染时重置钩子状态。
这是我试图修复标题的滚动小示例
class Header extends Component {
constructor(props) {
super(props);
console.log("Constructor")
this.state = {fixed: false};
}
handleScroll = () => {
console.log(window.scrollY);
console.log(this.state.fixed);
if (window.scrollY >= 25 && !this.state.fixed) {
this.setState({
fixed: true
});
} else if(window.scrollY < 25 && this.state.fixed){
this.setState({
fixed: false
});
}
}
componentDidUpdate(prevProps, prevState, snapshot) {
console.log("updated ");
}
componentDidMount() {
console.log("added");
window.addEventListener('scroll', this.handleScroll);
}
componentWillUnmount() {
console.log("removed");
window.removeEventListener('scroll', this.handleScroll);
}
render() {
return (
<div></div>
);
}
}
Run Code Online (Sandbox Code Playgroud)
输出:
Header.js:26 Constructor
Header.js:51 added
Header.js:32 1
Header.js:33 false
Header.js:32 2
Header.js:33 false
Header.js:32 5
Header.js:33 false
Header.js:32 9
Header.js:33 false
Header.js:32 15
Header.js:33 false
Header.js:32 20
Header.js:33 false
Header.js:32 26
Header.js:33 false
Header.js:47 updated
Header.js:32 31
Header.js:33 true
Header.js:32 35
Header.js:33 true
Header.js:32 38
Header.js:33 true
Header.js:32 40
Header.js:33 true
Header.js:32 39
Header.js:33 true
Header.js:32 38
Header.js:33 true
Header.js:32 35
Header.js:33 true
Header.js:32 31
Header.js:33 true
Header.js:32 25
Header.js:33 true
Header.js:32 20
Header.js:33 true
Header.js:47 updated
Header.js:32 9
Header.js:33 false
Header.js:32 5
Header.js:33 false
Header.js:32 2
Header.js:33 false
Header.js:32 0
Header.js:33 false
Run Code Online (Sandbox Code Playgroud)
它工作正常。
现在与反应挂钩相同的逻辑。我只是想寻找 FixedHeader 状态的行为。
const Header = props => {
console.log("rendering");
const [FixedHeader, setFixedHeader] = useState(false);
useEffect(() => {
document.addEventListener("scroll", () => {
console.log(window.scrollY);
console.log(FixedHeader);
if (window.scrollY >= 30) {
setFixedHeader(true);
} else {
setFixedHeader(false);
}
})
}, []);
return (
<div></div>
);
}
Run Code Online (Sandbox Code Playgroud)
输出:
Header.js:23 rendering
Header.js:28 1
Header.js:29 false
Header.js:28 2
Header.js:29 false
Header.js:28 5
Header.js:29 false
Header.js:28 9
Header.js:29 false
Header.js:28 15
Header.js:29 false
Header.js:28 20
Header.js:29 false
Header.js:28 26
Header.js:29 false
Header.js:28 31
Header.js:29 false
Header.js:23 rendering
Header.js:28 35
Header.js:29 false
Header.js:23 rendering
Header.js:28 38
Header.js:29 false
Header.js:28 40
Header.js:29 false
Header.js:28 39
Header.js:29 false
Header.js:28 38
Header.js:29 false
Header.js:28 35
Header.js:29 false
Header.js:28 31
Header.js:29 false
Header.js:28 25
Header.js:29 false
Header.js:23 rendering
Header.js:28 20
Header.js:29 false
Header.js:23 rendering
Header.js:28 14
Header.js:29 false
Header.js:28 9
Header.js:29 false
Header.js:28 5
Header.js:29 false
Header.js:28 2
Header.js:29 false
Header.js:28 0
Header.js:29 false
Run Code Online (Sandbox Code Playgroud)
我无法理解这种行为为什么渲染被调用两次,即使滚动 >= 30,FixedHeader 也是假的。
我是 js 的新手,所以我认为这是函数工作渲染的方式有 2 次,因为函数被调用了两次,但为什么两次,每次调用函数时,所有状态都需要再次设置,这不会影响性能(我可能是错的)。
注意:我没有添加 html 部分,它是简单的标题,我在其中添加了基于布尔变量的类“固定顶部”。
“渲染”显示两次的原因是因为您使用了不同的条件。
对于您使用的类组件:
if (window.scrollY >= 25 && !this.state.fixed) {
// ...
} else if (window.scrollY < 25 && this.state.fixed) {
// ...
}
Run Code Online (Sandbox Code Playgroud)
而函数组件使用:
if (window.scrollY >= 30) {
// ...
} else {
// ...
}
Run Code Online (Sandbox Code Playgroud)
要解决此问题,您需要添加检查当前状态。
然而,就像您已经注意到的那样,检查FixedHeader值将始终产生相同的值(它不会更新)。所以我们需要首先解决这个问题。
问题是setFixedHeader不会更新FixedHeader当前上下文中的。FixedHeader它告诉 React在下次调用时使用传递的值作为新值重新渲染Header,但FixedHeader在当前上下文中永远不会改变。
useEffect允许您返回处理清理的函数。如果组件卸载,或者在下一次调用之前useEffect(当依赖项列表发生更改时),此函数将运行。添加FixedHeader到依赖项列表将删除以前的滚动事件处理程序(使用返回的清理函数),并FixedHeader在FixedHeader值更改时使用新值添加新的滚动事件处理程序。
if (window.scrollY >= 25 && !this.state.fixed) {
// ...
} else if (window.scrollY < 25 && this.state.fixed) {
// ...
}
Run Code Online (Sandbox Code Playgroud)
if (window.scrollY >= 30) {
// ...
} else {
// ...
}
Run Code Online (Sandbox Code Playgroud)
const {useEffect, useState} = React;
const Header = props => {
console.log("rendering");
const [fixed, setFixed] = useState(false);
useEffect(() => {
const handleScroll = () => {
console.log(window.scrollY);
console.log(fixed);
if (window.scrollY >= 30 && !fixed) {
setFixed(true);
} else if (window.scrollY < 30 && fixed) {
setFixed(false);
}
};
document.addEventListener("scroll", handleScroll);
return () => document.removeEventListener("scroll", handleScroll);
}, [fixed]);
return null;
}
ReactDOM.render(<Header />, document.querySelector("#header-container"));Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
277 次 |
| 最近记录: |