如何将数组项一个接一个地添加到DOM?

时间:2018-11-14 07:46:11

标签: javascript reactjs loops iteration jsx

我想在Array.map完成其循环时,不逐批将数组中的项目逐个添加到DOM。 我该怎么办?

<div className="gallery-content">
    <div className="content-to-display">
          {iconsToDisplay
             .map((icon, index) => 
                <GalleryItem 
                   key={index}
                   index={index} 
                   item={icon}
                   size={iconSize}
                   isSelected={index===selectedIconIndex}
                   onClick={this.setIconIndex}/>)}
    </div>                
</div>

4 个答案:

答案 0 :(得分:1)

我认为一种方便的方法是先渲染加载微调器或占位符,然后在componentDidMount中的某个位置执行大量数据提取。

通过这种方式,您不必做任何延迟或手动调用appendChild,因为最初甚至可以快速渲染大量组件。

UPD:例如,请参见此jsfiddle。首先,用非常快的初始loading...消息来呈现画廊项目,然后我在componentDidMount内部模拟了沉重的负载,该状态已经用“已加载”的内容更新了状态,而React已经成功重新呈现它们。

答案 1 :(得分:0)

也许这样的事情可能有用: https://react-bootstrap.github.io/react-overlays/#portals

  

您可以将其视为声明性的appendChild()或jQuery的   $ .fn.appendTo()。组件的子代将被追加   到指定的容器。

答案 2 :(得分:0)

以下是一种替代方法:

您可以使索引和项目保持状态,并在每次渲染之前将项目添加到列表中,而不是在JSX中循环。像这样:

state = {
  index: 0,
  galleryItems: []
}

componentDidMount() {
   // manually triggers the first component update
   this.setState({ state: this.state });
}

componentDidUpdate() {
   let galleryItems = this.state.galleryItems
   let index = this.state.index

   // loops until it reaches to the end of list
   if(index < iconsToDisplay.length - 1) {
      galleryItems.push(
         <GalleryItem 
            key={index}
            index={index} 
            item={icon}
            size={iconSize}
            isSelected={index===selectedIconIndex}
            onClick={this.setIconIndex}/>)})

      this.setState({
         index: index + 1,
         galleryItems: galleryItems
      })
   }
}

然后,您可以在render()周期中呈现此列表。像这样:

render() {    
   return(
     <div className="content-to-display">
       { this.state.galleryItems }
     </div>
   )
}

这样,您就可以将它们一一渲染。

免责声明:我觉得这可能有效,但是我没有尝试过代码。我也怀疑它是否会以任何方式提高性能。我只是说这是一种可能的方法,也许值得一试。

答案 3 :(得分:0)

尝试使用计时器。请查看是否有帮助

enter image description here

import React, { Component } from "react";
import ReactDOM from "react-dom";

import "./styles.css";

class App extends Component {
  constructor() {
    super();
    this.icons = [100, 200, 201, 400, 401, 404, 500, 502, 503, 504];
    this.state = {
      iconsToPlot: [],
      message: "Rendering images...",
      pendingCount: this.icons.length
    };

    let timerHandle = setInterval(() => {
      let imgNo = this.icons.pop();
      if (imgNo) {
        let pendingCount = this.icons.length;
        this.setState({
          iconsToPlot: [...this.state.iconsToPlot, imgNo],
          pendingCount: pendingCount
        });
      } else {
        clearInterval(timerHandle);
        this.setState({ message: "Timer stoped as all images are rendered." });
      }
    }, 3000);
  }

  render() {
    return (
      <div>
        <p>
          {this.state.message} Remaining {this.state.pendingCount} images{" "}
        </p>
        <ul>
          {this.state.iconsToPlot.map((key, index) => (
            <li key={index}>
              <img src={`https://http.cat/${key}`} width="150" />
            </li>
          ))}
        </ul>
      </div>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

播放here