React出现未挂载组件状态更新警告 如何正确使用qs解析URL查询参数
「Can't perform a React state update on an unmounted component」警告修复
触发原因
- 异步接口请求返回时,组件已经被卸载,仍然执行
setProduct更新状态 - 你注释了socket的清理逻辑,组件卸载后socket的
status-update事件仍会触发,直接操作已经不存在的DOM节点
修复方案
- 在useEffect内新增挂载状态标记,异步请求完成后先判断组件是否仍挂载,再更新状态
- 恢复socket清理逻辑,组件卸载时主动断开连接、移除事件监听
- 替换原生
getElementByIdDOM操作为React状态管理,避免操作不存在的节点
修改后的useEffect代码参考:
const [statusText, setStatusText] = useState('Share') // 替换原DOM操作的状态 useEffect(() => { let isMounted = true // 解析查询参数可以移到顶层,这里先保留原有逻辑 const query = new URLSearchParams(match.location).get('sound'); console.log(`location is ${match.params}`); console.log('about to fetch product'); const fetchProduct = async () => { console.log('Below is the id param: ', match.params.id); const { data } = await axios.get(`http://localhost:5000/api/products/${match.params.id}`); // 仅挂载状态下更新state if (isMounted) { setProduct(data); } }; fetchProduct(); const socket = socketIOClient(ENDPOINT); const handleStatusUpdate = (call) => { // 用状态更新替代DOM操作 setStatusText(call) } socket.on('status-update', handleStatusUpdate); // 恢复清理逻辑 return () => { isMounted = false socket.off('status-update', handleStatusUpdate) socket.disconnect(); }; }, [match]);
渲染部分把原来的<h2 id='statusText'>Share</h2>改为<h2>{statusText}</h2>即可。
查询字符串解析位置调整
结论
函数组件不存在类组件的构造函数概念,不需要也不能放到所谓的构造函数中执行。qs.parse是纯同步计算操作,直接放在**组件顶层(useEffect外部)**执行即可,比放在useEffect中更合理。
优势
- 同步解析不会阻塞渲染,组件初始化时就能拿到参数值,不需要等待useEffect执行
- 脱离useEffect作用域限制,组件内所有逻辑都可以直接调用查询参数
- 路由
match参数变化时,会自动触发组件重新渲染,同步重新计算查询参数,不需要额外处理依赖
代码示例:
const ProductScreen = ({ match }) => { const [product, setProduct] = useState({}); const [state, setState] = useState(0); const [statusText, setStatusText] = useState('Share') // 顶层直接解析查询参数 const { sound } = qs.parse(match?.location?.search || '', { ignoreQueryPrefix: true }) // 后续逻辑可以直接使用sound变量,不需要放在useEffect内 // ...剩下的原有逻辑 }
内容的提问来源于stack exchange,提问作者jdog
相关产品推荐
相关产品推荐

