1、奇怪现象
在开发环境的严格模式下:以下两种情况effect回调都会执行两次
第一次执行effect回调时会打印第一个"组件挂载了",第二次执行时会先对上次的执行进行清理,所以打印"组件卸载了",最后第二次执行effect回调打印第二个"组件挂载了"
// 情况一
useEffect(() => {
console.log('组件挂载了')
return () => {
console.log('组件卸载了')
}
})
// 情况二
useEffect(() => {
console.log('组件挂载了')
return () => {
console.log('组件卸载了')
}
}, [])
在生产环境中不会出现这种现象
2、官方为何会这样做?
原因:为了通过挂载两次组件来提早发现你的问题。
import { useState, useEffect } from 'react'
function App() {
const [count, setCount] = useState(0)
useEffect(() => {
setInterval(() => {
setCount(count => count + 1)
}, 1000)
}, [])
return (
<div>count: {count}</div>
)
}
export default App;
上面这段代码中的App组件会挂载两次,同时有两个定时器运行,导致页面上的count会以count+2递增显示。 这个时候你就会发现代码有问题,从而你会主动加上清除定时器代码。如下。
import { useState, useEffect } from 'react'
function App() {
const [count, setCount] = useState(0)
useEffect(() => {
const timer = setInterval(() => {
setCount(count => count + 1)
}, 1000)
+ return () => clearInterval(timer)
}, [])
return (
<div>count: {count}</div>
)
}
export default App;
此时count的显示就正常了,以count+1递增显示。
另一种解决办法是不使用严格模式,如下
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
- //<React.StrictMode>
<App />
- //</React.StrictMode>
);
此时effect的表现在开发环境和生产环境保持一致。
总结
当你发现effect回调执行两次时,其实是React官方在通知你:你的代码不够好,赶紧优化一下吧!!!