React中使用react-if包时子组件偶尔不渲染的问题排查
使用react-if包时子组件偶尔渲染偶尔消失的问题解决
我在使用react-if包时,遇到子组件有时渲染、有时不显示的问题。入口代码如下:
ReactDOM.createRoot(document.getElementById('root')!).render( <React.StrictMode> <Example Component={App} /> </React.StrictMode> );
Example组件代码:
export const Example = ({ Component }) => { const fetchData = () => { return new Promise((resolve, reject) => { // 模拟异步操作(比如从服务器获取数据) setTimeout(() => { console.log('oooooooooo'); // 模拟成功响应 const data = { message: 'Data fetched successfully' }; return resolve(data); // 模拟错误 // reject(new Error('Failed to fetch data')); }, 2000); // 模拟2秒延迟 }); }; return ( <div> <If condition={fetchData()}> <Fallback>Loading data ...</Fallback> <Then> {(data) => ( <> <span>Here ish your data:{JSON.stringify(data)}</span> <Component /> </> )} </Then> <Else>{(error) => <span>Failed to load data because </span>}</Else> </If> </div> ); };
问题原因
- 渲染阶段直接调用异步函数:每次组件渲染时,
fetchData()都会创建一个新的Promise实例传给<If>的condition属性。React渲染是同步的,而Promise是异步的,这会导致react-if每次渲染都重新处理异步逻辑,状态不稳定,进而引发子组件显示异常。 - Strict Mode的双重渲染:开发环境下,
<React.StrictMode>会触发组件两次渲染以检测副作用,这会让fetchData()被调用两次,生成两个独立的Promise。react-if可能交替处理这两个Promise的结果,导致UI闪烁或子组件不显示。 - 未正确管理异步状态:没有用React状态保存异步操作的结果和阶段,直接把Promise传给
condition,破坏了react-if的内部状态管理逻辑。
解决方案
用useState和useEffect管理异步操作的状态,确保异步逻辑只执行一次,且状态稳定:
import { useState, useEffect } from 'react'; import { If, Then, Else, Fallback } from 'react-if'; export const Example = ({ Component }) => { const [data, setData] = useState(null); const [error, setError] = useState(null); const [loading, setLoading] = useState(true); const fetchData = () => { return new Promise((resolve, reject) => { setTimeout(() => { console.log('oooooooooo'); const data = { message: 'Data fetched successfully' }; resolve(data); // reject(new Error('Failed to fetch data')); }, 2000); }); }; useEffect(() => { const loadData = async () => { try { const result = await fetchData(); setData(result); } catch (err) { setError(err); } finally { setLoading(false); } }; loadData(); }, []); // 空依赖数组确保组件挂载时仅执行一次 return ( <div> <If condition={!loading && data}> <Fallback>Loading data ...</Fallback> <Then> <> <span>Here is your data:{JSON.stringify(data)}</span> <Component /> </> </Then> <Else> <span>Failed to load data because {error?.message}</span> </Else> </If> </div> ); };
修改说明
- 用
useState维护data(数据结果)、error(错误信息)、loading(加载状态)三个状态,明确异步操作的各个阶段。 - 用
useEffect在组件挂载时执行一次异步数据获取,避免重复调用和Strict Mode双重渲染的影响(即使Strict Mode调用两次useEffect,状态更新会被合并,不会导致异常)。 <If>的condition改为基于同步状态的判断,不再直接传递Promise,确保react-if的状态稳定,子组件渲染逻辑可靠。
内容的提问来源于stack exchange,提问作者user5711656
相关产品推荐
相关产品推荐

