简体   繁体   English

反应渲染组件仅几秒钟

[英]React render component only for few seconds

In my existing react component, I need to render another react component for a specific time period.在我现有的反应组件中,我需要在特定时间段内渲染另一个反应组件。 As soon as the parent component mounts/or data loads, the new-component (or child component) should be visible after 1-2 seconds and then after another few seconds, the new-component should be hidden.一旦父组件挂载/或数据加载,新组件(或子组件)应该在 1-2 秒后可见,然后再过几秒钟,新组件应该被隐藏。 This needs to be done only if there is no data available.只有在没有可用数据时才需要这样做。

This is what currently I've tried to achieve:这是我目前试图实现的目标:

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;

The current implementation is not working as expected.当前的实现没有按预期工作。 The new-component renders in a blink fashion.新组件以闪烁的方式呈现。

Here is the working snippet attached:这是附加的工作片段:

Any help to resolve this is appreciated!任何解决此问题的帮助表示赞赏!

Every time App renders, you create a brand new sampleData array.每次 App 渲染时,您都会创建一个全新的sampleData数组。 It may be an empty array each time, but it's a different empty array.每次可能都是一个空数组,但它是一个不同的空数组。 Since it's different, the useEffect needs to rerun every time, which means that after every render, you set a timeout to go off in 1 second and show the component.由于不同,useEffect 每次都需要重新运行,这意味着在每次渲染后,您将超时设置为 go 在 1 秒内关闭并显示组件。

If this is just a mock array that will never change, then move it outside of App so it's only created once:如果这只是一个永远不会改变的模拟数组,那么将它移到 App 之外,这样它就只创建一次:

const sampleData = [];

function App() {
  // ...
}

Or, you can turn it into a state value:或者,您可以将其转换为 state 值:

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

I have modified the code to work, hope this how you are expecting it to work .我已经修改了代码以使其正常工作,希望这是您期望的工作方式

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

I needed to do imperatively control rendering an animation component and make it disappear a few seconds later.我需要强制控制渲染 animation 组件并使其在几秒钟后消失。 I ended up writing a very simple custom hook for this.我最终为此编写了一个非常简单的自定义钩子。 Here's a link to a sandbox.这是沙盒的链接

NOTE: this is not a full solution for the OP's exact use case.注意:这不是 OP确切用例的完整解决方案。 It simply abstracts a few key parts of the general problem:它只是抽象了一般问题的几个关键部分:

  1. Imperatively control a conditional render命令式控制条件渲染
  2. Make the conditional "expire" after duration number of milliseconds.duration毫秒数之后使条件“过期”。

I hope this helps someone in the future.我希望这对将来的某人有所帮助。 Cheers.干杯。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM