React 功能组件:一旦达到 window 断点就尝试设置状态
React functional component: Trying to set a state once a window break point is reached
这是我的问题代码,我的问题是事件在到达 960px 断点时触发了多次。这应该只在到达断点时触发,但我得到的事件触发器数量几乎呈指数级增长。
const mediaQuery = '(max-width: 960px)';
const mediaQueryList = window.matchMedia(mediaQuery);
mediaQueryList.addEventListener('change', (event) => {
if (event.matches) {
setState((prevState) => ({
...prevState,
desktopNavActivated: false,
}));
} else {
setState((prevState) => ({
...prevState,
menuActivated: false,
navItemExpanded: false,
}));
}
});```
您好,欢迎来到 Whosebug!
我假设,当我第一次开始使用效果时,您的代码在 useEffect
hook, which will result in a new event listener being added to your mediaQueryList
every time your component gets updated/rendered. This would explain the exponential amount of triggers. The useEffect
hook can be quite unintuitive at first, so I recommend reading up on it a bit. The docs do quite a good job at explaining the concept. I also found this article by Dan Abramov 内不会 运行 非常有用。
你调用 setState
函数的方式总是会导致你的组件更新,无论当前状态是否已经匹配你的媒体查询,因为你每次都向它传递一个新对象更新。与基于 class 的组件的 setState
方法(比较对象 key/values iirc)不同,hook 版本仅在确定更新是否应触发重新渲染时检查 strict equality .一个例子:
{ foo: 'bar' } === { foo: 'bar' } // Always returns false. Try it in your console.
为了防止这种情况发生,您可以设置一个状态挂钩,它实际上只跟踪比赛结果并从中派生出您的标志。布尔值在引用相等时工作得很好:
const [doesMatch, setDoesMatch] = useState(false)
所以把它们放在一起:
const mediaQuery = '(max-width: 960px)';
const mediaQueryList = window.matchMedia(mediaQuery);
const MyComponent = () =>
const [match, updateMatch] = useState(false)
useEffect(() => {
const handleChange = (event) => {
updateMatch(event.matches)
}
mediaQueryList.addEventListener('change', handleChange)
return () => {
// This is called the cleanup phase aka beforeUnmount
mediaQueryList.removeEventListener('change', handleChange)
}
}, []) // Only do this once, aka hook-ish way of saying didMount
const desktopNavActivated = !match
// ...
// Further process your match result and return JSX or whatever
}
再一次,我真的建议你在有空的时候仔细阅读 React 文档和一些文章。 Hooks 很棒,但如果不了解基本概念,使用它们会很快变得非常令人沮丧。
这是我的问题代码,我的问题是事件在到达 960px 断点时触发了多次。这应该只在到达断点时触发,但我得到的事件触发器数量几乎呈指数级增长。
const mediaQuery = '(max-width: 960px)';
const mediaQueryList = window.matchMedia(mediaQuery);
mediaQueryList.addEventListener('change', (event) => {
if (event.matches) {
setState((prevState) => ({
...prevState,
desktopNavActivated: false,
}));
} else {
setState((prevState) => ({
...prevState,
menuActivated: false,
navItemExpanded: false,
}));
}
});```
您好,欢迎来到 Whosebug!
我假设,当我第一次开始使用效果时,您的代码在
useEffect
hook, which will result in a new event listener being added to yourmediaQueryList
every time your component gets updated/rendered. This would explain the exponential amount of triggers. TheuseEffect
hook can be quite unintuitive at first, so I recommend reading up on it a bit. The docs do quite a good job at explaining the concept. I also found this article by Dan Abramov 内不会 运行 非常有用。你调用
setState
函数的方式总是会导致你的组件更新,无论当前状态是否已经匹配你的媒体查询,因为你每次都向它传递一个新对象更新。与基于 class 的组件的setState
方法(比较对象 key/values iirc)不同,hook 版本仅在确定更新是否应触发重新渲染时检查 strict equality .一个例子:
{ foo: 'bar' } === { foo: 'bar' } // Always returns false. Try it in your console.
为了防止这种情况发生,您可以设置一个状态挂钩,它实际上只跟踪比赛结果并从中派生出您的标志。布尔值在引用相等时工作得很好:
const [doesMatch, setDoesMatch] = useState(false)
所以把它们放在一起:
const mediaQuery = '(max-width: 960px)';
const mediaQueryList = window.matchMedia(mediaQuery);
const MyComponent = () =>
const [match, updateMatch] = useState(false)
useEffect(() => {
const handleChange = (event) => {
updateMatch(event.matches)
}
mediaQueryList.addEventListener('change', handleChange)
return () => {
// This is called the cleanup phase aka beforeUnmount
mediaQueryList.removeEventListener('change', handleChange)
}
}, []) // Only do this once, aka hook-ish way of saying didMount
const desktopNavActivated = !match
// ...
// Further process your match result and return JSX or whatever
}
再一次,我真的建议你在有空的时候仔细阅读 React 文档和一些文章。 Hooks 很棒,但如果不了解基本概念,使用它们会很快变得非常令人沮丧。