仅反应渲染组件几秒钟

React render component only for few seconds

在我现有的反应组件中,我需要在特定时间段内渲染另一个反应组件。 一旦父组件 mounts/or 数据加载,新组件(或子组件)应该在 1-2 秒后可见,然后再过几秒,新组件应该隐藏。只有在没有可用数据时才需要这样做。

这是我目前努力实现的目标:

import React, { useState, useEffect } from "react";

function App() {
  const [showComponent, setShowComponent] = useState(false);
  const sampleData = [];

  useEffect(() => {
    if (sampleData.length === 0) {
      setTimeout(() => {
        setShowComponent(true);
      }, 1000);
    }
  }, [sampleData]);

  useEffect(() => {
    setTimeout(() => {
      setShowComponent(false);
    }, 4000);
  }, []);

  const componentTwo = () => {
    return <h2>found error</h2>;
  };

  return <>First component mounted{showComponent && componentTwo()}</>;
}

export default App;

当前的实现没有按预期工作。新组件以闪烁方式呈现。

附上工作片段:

感谢任何解决此问题的帮助!

每次 App 渲染时,您都会创建一个全新的 sampleData 数组。可能每次都是一个空数组,但它是一个不同的空数组。由于不同,useEffect 每次都需要重新运行,这意味着在每次渲染后,您设置超时以在 1 秒内关闭并显示组件。

如果这只是一个永远不会改变的模拟数组,那么将它移到 App 之外,这样它只创建一次:

const sampleData = [];

function App() {
  // ...
}

或者,你可以把它变成一个状态值:

function App() {
  const [showComponent, setShowComponent] = useState(false);
  const [sampleData, setSampleData] = useState([]);
  // ...
}

我已经修改了代码,希望它能像您期望的那样工作

import React, { useState, useEffect } from "react";

const sampleData = [];
// this has to be out side or passed as a prop
/* 
reason: when the component render (caued when calling setShowComponent) 
a new reference is created for "sampleData", this cause the useEffect run every time the component re-renders,
 resulting "<h2>found error</h2>" to flicker.
*/

function App() {
  const [showComponent, setShowComponent] = useState(false);

  useEffect(() => {
    if (sampleData.length === 0) {
      const toRef = setTimeout(() => {
        setShowComponent(true);
        clearTimeout(toRef);
        // it is good practice to clear the timeout (but I am not sure why)
      }, 1000);
    }
  }, [sampleData]);

  useEffect(() => {
    if (showComponent) {
      const toRef = setTimeout(() => {
        setShowComponent(false);
        clearTimeout(toRef);
      }, 4000);
    }
  }, [showComponent]);

  const componentTwo = () => {
    return <h2>found error</h2>;
  };

  return <>First component mounted{showComponent && componentTwo()}</>;
}

export default App;

You can try this for conditional rendering.

import { useEffect, useState } from "react";
import "./styles.css";

const LoadingComponent = () => <div>Loading...</div>;

export default function App() {
    const [isLoading, setLoading] = useState(true);
    const [isError, setIsError] = useState(false);

    const onLoadEffect = () => {
        setTimeout(() => {
            setLoading(false);
        }, 2000);

        setTimeout(() => {
            setIsError(true);
        }, 10000);
    };

    useEffect(onLoadEffect, []);

    if (isLoading) {
        return <LoadingComponent />;
    }
    return (
        <div className="App">
            {isError ? (
                <div style={{ color: "red" }}>Something went wrong</div>
            ) : (
                <div>Data that you want to display</div>
            )}
        </div>
    );
}