-1

I am trying to implement infinite-scroll to my blog, I have

const articlesHTML = document.querySelector(".articles");

as container. On each click on Load more button I want to append the new articles to the main html element, like this:

const results = articles
      .slice(0, 10 * pager)
      .map((articleID, i) => (
        <Article key={i} id={articleID} />
      ));
articlesHTML.append(results);

however, results is bunch of <Article/> react components not html nodes, am I missing something?

Nguyễn Văn Phong
  • 13,506
  • 17
  • 39
  • 56
MMJ
  • 279
  • 7
  • 23
  • 1
    You generally wouldn't use DOM methods like `append` to achieve the results you are looking for within React. How are you rendering `Articles` within your component? – wlh Jan 24 '20 at 15:53
  • 1
    `Article` is really just a javascript function, you can't append it and expect it to turn into HTML – Brian Thompson Jan 24 '20 at 15:54
  • @wlh I am rendering `Articles` only two times as a react-router routes, depending on the query - **Top** or **Best** articles - in the url param. – MMJ Jan 24 '20 at 16:06

2 Answers2

3

You could use render from ReactDOM to render the components into a hidden HTML node and then append the contents of that node to another node.

But using React's output like that is generally a bad idea. What I would suggest is building the entire component in React.

For example:

const App = () => {
    const [articles, setArticles] = useState([]);
    const loadMore = useCallback(() => {
        setArticles(...);
    }, [setArticles]);

    return (
        <div className="app">
             {articles.map((article) => <Article key={article.uuid} ... />)}
             <button onClick={loadMore}>Load more</button>
        </div>
    );
};
Mat Sz
  • 2,524
  • 1
  • 10
  • 23
  • This is pretty much how I am doing expect I am putting the JavaScript logic you have in a `renderArticle()` function because I have too much code there... then returning the `
    `s loop just like the way you did it.
    – MMJ Jan 24 '20 at 16:09
  • You shouldn't do it this way. Take a look at the official React documentation, particularly ReactDOM.render – Mat Sz Jan 24 '20 at 16:11
1

You can try like this by using Array.slice() - Demo

class Home extends React.PureComponent {
  constructor(props) {
    super(props);
    this.state = {
      lists: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
      limit: 3
    };
  }
  addMore = () => this.setState(prev => ({ limit: prev.limit + 3 }));
  render() {
    const { lists, limit } = this.state;
    return (
      <div>
        {lists.slice(0, limit).map(list => (
          <p style={{ background: "lightgrey" }} key={list}>
            {list}
          </p>
        ))}
        {limit !== lists.length && (
        <button onClick={this.addMore}>Load More</button>
        )}
      </div>
    );
  }
}
akhtarvahid
  • 9,445
  • 2
  • 26
  • 29