单击按钮后如何在组件内部渲染额外的组件?

时间:2019-05-13 16:32:18

标签: javascript reactjs

我有一些博客文章需要呈现。显示了前4个。单击其下方的按钮时,还需要显示两个。再次单击该按钮时,需要再显示两个,依此类推。 不幸的是,我无法这样做。

这是我的代码:

import React from 'react';
import axios from 'axios';
import Blogpost from './Blogpost.js';

class BlogpostReader extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      error: null,
      isLoaded: false,
      blogposts: [],
    };
  }

  componentDidMount() {
    // Loading all blogposts in state
  }

  renderBlogpost(i) {
    // Render one blogpost
  }

//This function has to be replaced by one that renders extra blogposts
    showAlert(){
      alert("Im an alert");
    }

    render() {
      const {error, isLoaded} = this.state;
      if (error) {
        return <div>Error: {error.message}</div>;
      } else if (!isLoaded) {
        return <div>Loading...</div>;
      } else {
        for (let i = 1; i < this.state.blogposts.length && i < 5; i++) {
          this.state.renderedBlogposts.push(
            <div key={this.state.blogposts[i].id} className="col-12 col-sm-12 col-md-12 col-lg-6 col-xl-6 whole-blogpost">
              {this.renderBlogpost(this.state.blogposts[i])}
            </div>)
        }
        return (
          <div>
            <div className="row">
              {this.state.renderedBlogposts}
            </div>
            <div className="centered-button">
              <button className="styled-button" onClick={this.showAlert}>Meer laden</button>
            </div>
          </div>
        );
      }
    }
  }

export default BlogpostReader;

单击按钮后如何显示其他博客文章?请帮帮我!

6 个答案:

答案 0 :(得分:0)

您可以执行以下操作:

 import React from 'react';
    import axios from 'axios';
    import Blogpost from './Blogpost.js';

    class BlogpostReader extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          error: null,
          isLoaded: false,
          blogposts: [],
          count:5
        };
      }

      componentDidMount() {
        // Loading all blogposts in state
        if(blogposts.length<5){
          this.setState({
            count:blogposts.length
          })
        }
      }
      renderBlogpost(i) {
        // Render one blogpost
      }
      renderBlogposts(){
        const blogposts=[];
        const count=this.state.count;
        for (let i = 1; i < count; i++) {
          blogposts.push(
            <div key={this.state.blogposts[i].id} className="col-12 col-sm-12 col-md-12 col-lg-6 col-xl-6 whole-blogpost">
              {this.renderBlogpost(this.state.blogposts[i])}
            </div>)
        }
        return blogposts;
      }

    //This function has to be replaced by one that renders extra blogposts
        addMore=()=>{
          let newCount=this.state.count + 2;
          if(this.state.count===this.state.blogposts.length) return;
          if(this.state.count+1 === this.state.blogposts.length){
            newCount=this.state.count+1
          }
          this.setState({
            count:newCount
          })
        }

        render() {
          const {error, isLoaded} = this.state;
          if (error) {
            return <div>Error: {error.message}</div>;
          } else if (!isLoaded) {
            return <div>Loading...</div>;
          } 

            return (
              <div>
                <div className="row">
                  {this.renderBlogposts()}
                </div>
                <div className="centered-button">
                  <button className="styled-button" onClick={this.addMore}>Meer laden</button>
                </div>
              </div>
            );
          }
        }
      }

答案 1 :(得分:0)

哦,亲爱的。在React中,推荐的方法是使事情尽可能声明。这意味着不必强制将项目推到数组上然后渲染该数组,而只需渲染数组的一部分即可。

即尝试这样的事情

class BlogpostReader extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      error: null,
      isLoaded: false,
      blogposts: [], // this will contain all posts
      postsToShow: 2, // a simple number controls how many posts are shown
    };
  }

  componentDidMount() {
    // Loading all blogposts in state
  }

  increasePostsShown() {
    this.setState(({ postsToShow }) => {
      postsToShow: postsToShow + 1;
    });
  }

  render() {
    const { error, isLoaded, blogposts, postsToShow } = this.state;
    if (error) {
      return <div>Error: {error.message}</div>;
    } else if (!isLoaded) {
      return <div>Loading...</div>;
    }

    const postsShown = blogposts.slice(0, postsToShow); // get only the ones you want to show
    return (
      <div>
        <div className="row">
          {postsShown.map(blog => (
            <div>{blog}</div> {/* or display them however you like */}
          ))}
        </div>
        <div className="centered-button">
          <button className="styled-button" onClick={this.increasePostsShown}>
            Meer laden
          </button>
        </div>
      </div>
    );
  }
}

答案 2 :(得分:0)

您的博客文章数组是否已包含所有博客文章?我的建议是,每当用户单击按钮时,您就从状态中增加一个值。

this.state = {
      error: null,
      isLoaded: false,
      blogposts: [],
      nbPostToDisplay: 4
    };

在您的循环中:

for (let i = 0 /* start at 0, not 1 */; i < this.state.blogposts.length && i < nbPostToDisplay; i++) {

一些要增加的功能:

function incrementNbPosts() {
  this.setState(prevState => return ({nbPOstsToDisplay: prevState.nbPostsToDisplay + 2});
}

在按钮回调中使用上面的函数。这将触发您的组件的重新渲染。

重要提示:不要忘记在构造函数中绑定功能,或者(最好)使用ES6表示法。

答案 3 :(得分:0)

这就是您所需要的。我还整理了一下代码

class BlogpostReader extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      error: null,
      isLoaded: false,
      blogposts: [],
      limit: 4
    };
    this.showMore = this.showMore.bind(this);
    this.renderBlogpost = this.renderBlogpost.bind(this);
  }

  componentDidMount() {
    // Loading all blogposts in state
  }

  renderBlogpost(i) {
    // Render one blogpost
  }

  //This function has to be replaced by one that renders extra blogposts
  showMore() {
    this.setState(state => ({ limit: state.limit + 2 }));
  }

  render() {
    const { error, isLoaded, blogpost, limit } = this.state;
    if (error) {
      return <div>Error: {error.message}</div>);
    }

    if (!isLoaded) {
      return <div>Loading...</div>;
    }

    return (
      <div>
        <div className="row">
          {
            blogposts.map((post, index) => {
              if (index + 1 !== limit) {
                return (
                  <div key={post.id} className="col-12 col-sm-12 col-md-12 col-lg-6 col-xl-6 whole-blogpost">
                    { this.renderBlogpost(post) }
                  </div>
                );
              }
            })
          }
        </div>
        <div className="centered-button">
          <button className="styled-button" onClick={this.showMore}>Meer laden</button>
        </div>
      </div>
    );
  }
}

如果您还想让showMore接受任意数量的帖子,则可以执行此操作...

showMore(value = 2) {
  this.setState(state => ({ limit: state.limit + value }));
}

然后,您可以使用任意数量的帖子来调用它。如果您未指定任何值,则限制将增加2。

更新

由于您已经提到必须在索引为1时开始,所以您可以像这样在blogposts.map中更新render

{
  blogposts.map((post, index) => {
    if (index && index !== limit) {
      // the condition above ensures that the posts at index 0, and also when index equals limit, are not returned

      // the rest of the code goes here...
    }
  })
}

这样做之后,如果只想在第一次加载时仅显示4个条目,则可以在构造函数中将limit设置为5。

答案 4 :(得分:0)

我最好使事情保持简单,以便该按钮仅用+1帖子设置新的state.posts,从而触发render(),从而依次渲染添加的元素。

 addPost = () => {
    ...
    this.setState({
      posts: [...posts, { id: posts.length + 1 }]
    });
  };

  renderPosts = () => {
    ...
  };

  render() {
    return (
      <div>
        <button onClick={this.addPost}>Add</button>
        {this.renderPosts()}
      </div>
    );
  }

制作了一个快速沙箱,用于说明提供的代码。 https://codesandbox.io/embed/vjlp468jk7

答案 5 :(得分:0)

以下是工作代码:

class BlogpostReader extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      error: null,
      isLoaded: false,
      blogposts: [],
      limit: 5,
      start: 1
    };

    this.showMore = this.showMore.bind(this);
  }

  componentDidMount() {
    // Loading all blogposts into state
  }

  renderBlogpost(i) {
    // Render a single blogost
  }

  showMore(){
    this.setState(state => ({
      start: state.limit,
      limit: state.limit + 2
    }));
  }

  render() {
    const {error, isLoaded, limit} = this.state;
    if (error) {
      return <div>Error: {error.message}</div>;
    } else if (!isLoaded) {
      return <div>Loading...</div>;
    } else {
      var startedAt = this.state.start
      for (startedAt; startedAt < this.state.blogposts.length && startedAt < limit; startedAt++) {
        this.state.renderedBlogposts.push(
          <div key={this.state.blogposts[startedAt].id} className="col-12 col-sm-12 col-md-12 col-lg-6 col-xl-6 whole-blogpost">
            {this.renderBlogpost(this.state.blogposts[startedAt])}
          </div>
        )
      }
      return (
        <div>
          <div className="row">
            {this.state.renderedBlogposts}
          </div>
          <div className="centered-button">
            <button className="styled-button" onClick={this.showMore}>Meer laden</button>
          </div>
        </div>
      );
    }
  }
}