Как добавить событие, чтобы отреагировать на функцию и выполнить рендеринг функции - PullRequest
0 голосов
/ 27 сентября 2019

У меня есть функция, которая отображает контент на странице на основе состояния, заполненного данными API, но мне нужно событие onClick, чтобы уточнить этот контент;

Так что в настоящее время getPosts возвращает информацию из сообщений состояния', которая снабжена данными из нашего API, но я хочу дополнительно отфильтровать этот контент, поэтому моя идея состоит в том, чтобы иметь какой-то прослушиватель событий, и, если это необходимо, изменить данные, поступающие из getPosts.

constructor() {
    super();
    this.state = {
        posts: ""
    }
    this.getPosts = this.getPosts.bind(this);
}
async componentWillMount(){
    var data = await api.posts();
    this.setState({posts: data.data});
    console.log(this.state.posts);
}
getPosts(type){
        if(this.state.posts.length){
            return this.state.posts.map((content,index) => {
                var url = content.Title.replace(/[^\w\s]/gi, '');
                url = url.replace(/\s+/g, '-').toLowerCase();
                if(type === content.PostType){
                    //output something different
                }
                else{
                    return(
                        <Col md={4} className="mb-4" key={index}>
                            {content.title}
                        </Col>
                    );
                }
            })

        }
    }
    render() {
        return (
            <div>
            <p><button onClick={()=>{this.getPosts('blog')}}>blog</button> <button onClick={()=>{this.getPosts('news')}}>news</button></p>
            {this.getPosts()}
            </div>
        )
    }

Так что мой getPosts работает нормально без какого-либо типа, как заставить его повторно выводить функцию на странице, основанную на событии onClick?

Ответы [ 2 ]

1 голос
/ 27 сентября 2019

Не вдаваясь в сложности контекста и ключей, компонент требует изменения реквизита или состояния для повторного рендеринга. Чтобы узнать больше о состоянии и жизненном цикле компонента, в документах есть отличное объяснение для компонентов класса.

Ваш компонент не выполняет рендеринг повторно после вызова onClick обработчика события getPosts, поскольку getPosts не обновляет внутреннее состояние компонента.getPosts работает в рендере, потому что эти значения возвращаются в React.Используя getPosts в качестве обработчика событий onClick, вы создаете элементы React и пытаетесь вернуть их в окно.

То, что следует, следует рассматривать как код psuedo, который показывает, как запустить компонент для рендеринга.разные посты:

  • Попробуйте добавить еще один ключ к состоянию в вашем конструкторе,
constructor(props) {
  super(props);
  this.state = {
    posts: "",
    type: null
  };
  this.getPosts = this.getPosts.bind(this);
  this.onClick = this.onClick.bind(this);
}
  • и создать обработчик кликов, который не пытается вернуть Reactelements
function onClick(evt) {
  this.setState({ type: evt.target.value });
}
  • и значения для ваших кнопок
<button onClick={this.onClick} type="button" value="blog">blog</button>
  • Теперь ваша кнопка обновит состояние с вашим новым типом записи, вызывая вашкомпонент для повторного рендеринга:
render() {
  return (
    <div>
      <p>
        <button onClick={this.onClick} type="button" value="blog">blog</button>
        <button onClick={this.onClick} type="button" value="news">news</button>
      </p>
      {this.getPosts()}
    </div>
  );
}

С типом содержимого, сохраненным в состоянии, теперь вы можете реализовать свой вызов getPosts любым удобным для вас способом.Удачи!

Это отклоняется от заданного вопроса, но стоит отметить, что componentWillMount не рекомендуется, а componentDidMount является предпочтительной функцией жизненного цикла для побочных эффектов и асинхронного поведения. К счастью, в документации много деталей!

0 голосов
/ 27 сентября 2019

Хорошо, поэтому вам следует начать с изменения значения по умолчанию this.state на

this.state = {
  posts: []
}

. Помните, что вы хотите перебирать массив данных вместо перебора строки, что приведет к ошибке, если вы сделаете это.это, так что лучше с самого начала сохраняйте тип данных, который вы хотите использовать.

Тогда вам нужно разделить ответственность за ваш getPosts метод, может быть, getPostByType - лучшее название для этого, так что у вас есть

getPostByType(type) {
  // if type is same as content.PostType then return it;
  const nextPosts = this.state.posts.filter((content) => type === content.PostType);
  this.setState({ posts: nextPosts });
}

и, наконец, вы можете перебирать сообщения, как это

render() {
  // better use content.id if exists instead of index, this is for avoid problems 
  // with rerender when same index key is applied.
  const posts = this.state.posts.map((content, index) => (
    <Col md={4} className="mb-4" key={content.id || index}>
      {content.title}
    </Col>
  ));
  return (
    <div>
      <button onClick={() => this.getPostByType('blog')}>Show Blog Posts</button>
      {posts}
    </div>
  );
}

Затем вы можете использовать getPostsByType в любое время в любом событии клика, передавая тип, который вы хотите отобразить.

...