You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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>
  );
};

问题原因

  1. 渲染阶段直接调用异步函数:每次组件渲染时,fetchData()都会创建一个新的Promise实例传给<If>的condition属性。React渲染是同步的,而Promise是异步的,这会导致react-if每次渲染都重新处理异步逻辑,状态不稳定,进而引发子组件显示异常。
  2. Strict Mode的双重渲染:开发环境下,<React.StrictMode>会触发组件两次渲染以检测副作用,这会让fetchData()被调用两次,生成两个独立的Promise。react-if可能交替处理这两个Promise的结果,导致UI闪烁或子组件不显示。
  3. 未正确管理异步状态:没有用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 17:28:38