延迟渲染React组件

mic*_*sek 39 javascript reactjs

我有一个React组件,其中包含许多子组件.我想不是一次性渲染子组件,而是在延迟一段时间后(每个孩子统一或不同).

我在想 - 有没有办法怎么做?

Mic*_*ker 48

我认为最直观的方法是给孩子们一个"等待" prop,它会将组件隐藏在从父母传递下来的持续时间内.通过将默认状态设置为隐藏,React仍将立即呈现组件,但在状态发生更改之前它将不可见.然后,您可以设置componentWillMount调用函数以在通过props传递的持续时间之后显示它.

var Child = React.createClass({
    getInitialState : function () {
        return({hidden : "hidden"});
    },
    componentWillMount : function () {
        var that = this;
        setTimeout(function() {
            that.show();
        }, that.props.wait);
    },
    show : function () {
        this.setState({hidden : ""});
    },
    render : function () {
        return (
            <div className={this.state.hidden}>
                <p>Child</p>
            </div>
        )
    }
});
Run Code Online (Sandbox Code Playgroud)

然后,在Parent组件中,您需要做的就是在显示Child之前传递您希望Child等待的持续时间.

var Parent = React.createClass({
    render : function () {
        return (
            <div className="parent">
                <p>Parent</p>
                <div className="child-list">
                    <Child wait={1000} />
                    <Child wait={3000} />
                    <Child wait={5000} />
                </div>
            </div>
        )
    }
});
Run Code Online (Sandbox Code Playgroud)

这是一个演示

  • 如果您对问题中描述的问题有更好的解决方案,欢迎您发布. (4认同)
  • 我们需要在componentWillUnmount中使用clearTimeout吗? (4认同)
  • 对我来说似乎很烦人.为什么要强制等待异步操作...你可以完全劫持性能而不是以某种方式延迟加载并行组件? (3认同)

Bla*_*ack 19

我使用Hooks 和 TypeScript创建了延迟组件

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

type Props = {
  children: React.ReactNode;
  waitBeforeShow?: number;
};

const Delayed = ({ children, waitBeforeShow = 500 }: Props) => {
  const [isShown, setIsShown] = useState(false);

  useEffect(() => {
    setTimeout(() => {
      setIsShown(true);
    }, waitBeforeShow);
  }, [waitBeforeShow]);

  return isShown ? children : null;
};

export default Delayed;
Run Code Online (Sandbox Code Playgroud)

只需将另一个组件包装到 Delayed

export function LoadingScreen = () => {
  return (
    <Delayed>
      <div />
    </Delayed>
  );
};
Run Code Online (Sandbox Code Playgroud)

  • @IanHaggerty 我已将其添加到解决方案中。感谢您提出宝贵的建议。 (5认同)
  • 很好的解决方案。如果组件卸载,您不应该清除超时吗?https://upmostly.com/tutorials/settimeout-in-react-components-using-hooks#:~:text=To%20clear%20or%20cancel%20a,of%20a%20function%20React%20component.&amp;text=。 ..,(()%20%3D%3E%20控制台。 (2认同)

gce*_*edo 10

在您的父组件中<Father />,您可以创建一个初始状态,在该状态中跟踪每个子项(例如,使用和id),指定一个布尔值,这意味着是否呈现:

getInitialState() {
    let state = {};
    React.Children.forEach(this.props.children, (child, index) => {
        state[index] = false;
    });
    return state;
}
Run Code Online (Sandbox Code Playgroud)

然后,在安装组件时,启动计时器以更改状态:

componentDidMount() {
    this.timeouts = React.Children.forEach(this.props.children, (child, index) => {
         return setTimeout(() => {
              this.setState({ index: true; }); 
         }, child.props.delay);
    });
}
Run Code Online (Sandbox Code Playgroud)

渲染子项时,可以通过重新创建它们,将匹配子项的状态指定为prop,指示是否必须呈现组件.

let children = React.Children.map(this.props.children, (child, index) => {
    return React.cloneElement(child, {doRender: this.state[index]});
});
Run Code Online (Sandbox Code Playgroud)

所以在你的<Child />组件中

render() {
    if (!this.props.render) return null;
    // Render method here
}
Run Code Online (Sandbox Code Playgroud)

触发超时后,将更改状态并重新呈现父组件.儿童道具会更新,如果doRendertrue,他们会自行渲染.

  • 非常感谢您的回答!尽管我选择了 Michael 的答案(因为它更适合我的情况),但您的答案 ** 也正确** 并且可能适合其他人阅读本文。非常感谢您的时间! (3认同)

gou*_*oup 10

延迟组件的另一种方法:

Delayed.jsx:

import React from 'react';
import PropTypes from 'prop-types';

class Delayed extends React.Component {

    constructor(props) {
        super(props);
        this.state = {hidden : true};
    }

    componentDidMount() {
        setTimeout(() => {
            this.setState({hidden: false});
        }, this.props.waitBeforeShow);
    }

    render() {
        return this.state.hidden ? '' : this.props.children;
    }
}

Delayed.propTypes = {
  waitBeforeShow: PropTypes.number.isRequired
};

export default Delayed;
Run Code Online (Sandbox Code Playgroud)

用法:

 import Delayed from '../Time/Delayed';
 import React from 'react';

 const myComp = props => (
     <Delayed waitBeforeShow={500}>
         <div>Some child</div>
     </Delayed>
 )
Run Code Online (Sandbox Code Playgroud)

  • 这太棒了。应标记为解决方案。 (5认同)

ano*_*ewb 6

使用 useEffect 钩子,我们可以在输入字段中输入时轻松实现延迟功能:

import React, { useState, useEffect } from 'react'

function Search() {
  const [searchTerm, setSearchTerm] = useState('')

  // Without delay
  // useEffect(() => {
  //   console.log(searchTerm)
  // }, [searchTerm])

  // With delay
  useEffect(() => {
    const delayDebounceFn = setTimeout(() => {
      console.log(searchTerm)
      // Send Axios request here
    }, 3000)

    // Cleanup fn
    return () => clearTimeout(delayDebounceFn)
  }, [searchTerm])

  return (
    <input
      autoFocus
      type='text'
      autoComplete='off'
      className='live-search-field'
      placeholder='Search here...'
      onChange={(e) => setSearchTerm(e.target.value)}
    />
  )
}

export default Search
Run Code Online (Sandbox Code Playgroud)