javascript - react hooks 和 react class 的性能对比
问题描述
我正在尝试学习反应钩子。我需要帮助来理解反应函数是否总是在每次渲染时重置钩子状态。
这是一个滚动的小示例,我正在尝试修复标题
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>
);
}
}
输出:
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
它工作正常。
现在使用 react hooks 相同的逻辑。我只是想寻找 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>
);
}
输出:
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
我无法理解为什么会调用两次渲染,并且即使滚动> = 30,FixedHeader 也是错误的。
我是 js 新手,所以我认为这是函数工作渲染存在 2 次的方式,因为函数被调用了两次,但为什么调用了两次,每次调用函数时,所有状态都需要重新设置,这不会影响性能(我可能错了)。
注意:我没有添加 html 部分,它是简单的标题,我在其中添加基于布尔变量的类“fixed-top”。
解决方案
我无法理解为什么会调用两次渲染,并且即使滚动> = 30,FixedHeader 也是错误的。
我猜是因为闭包,函数记住了 FixedHeader 值,它马上就有了,函数被创建了......如果你真的需要在滚动中查看值,你可以在组件外部创建一些对象并将 FixedHeader 写入它的属性事件回调
const holder = {}
const Header = props => {
const [FixedHeader, setFixedHeader] = useState('false');
holder.value = FixedHeader
const handleScroll = function () {
console.log(window.scrollY)
console.log(holder.value)
if (window.scrollY >= 30) {
setFixedHeader('true');
} else {
setFixedHeader('false');
}
}
useEffect(() => {
document.addEventListener("scroll", handleScroll)
return () => window.removeEventListener('scroll', handleScroll);
}, []);
return (
但由于反应不会立即重新渲染,有时价值不会正确
推荐阅读
- python - 在 python 脚本中运行 bash source 命令
- node.js - 是否可以使用 pm2 reload 命令仅使用一个 pm2 fork 模式实例将停机时间归零?
- r - 在特定观察后提取第一个值
- http - 为什么flush会出现死锁?
- vim - 如何在不删除 Vim 中的括号的情况下删除括号内的所有内容?
- node.js - 如何使用 google oAuth 库在本地验证 Google 访问令牌
- ios - 在 React Native 中使用 Apple 登录返回 null
- python - 将 2 个一维数组转换为 1 个二维数组 Numpy Python
- python - ModuleNotFoundError:没有名为“deepface”的模块
- c# - 编辑时小数列的 RadGridView 千位分隔符