Внесите изменения в выборку API onClick в React - PullRequest
0 голосов
/ 31 октября 2019

Я создаю прототип пользовательского интерфейса и извлекаю данные из API, подобного этому, в React:

  componentWillUpdate() {
    fetch(this.state.api + this.state.query  +".json" + this.state.key)
      .then(response => {
        if (response.ok) {
          return response.json();
        } else {
          throw new Error('Oops')
        }
      })
      .then(data => this.setState({ results: data.results, isLoading: false}))
      .catch(error => this.setState({ error, isLoading: false }))
  }

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

<li data-facet="arts" onClick={this.handleCategory}>Arts</li>

и метода-обработчика, подобного следующему:

handleCategory(event) {
    this.setState({
      query: event.target.getAttribute('data-facet')
    })
  }

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


Обновление с полным кодом компонента:

import React, { Component } from 'react'
import Moment from 'moment'
import MaterialIcon from 'material-icons-react'
import '../assets/styles/app.scss'

class App extends Component {

  constructor(props) {
    super(props);
    this.state = {
      error: null,
      isLoading: false,
      isMenuOpen: false,
      results: [],
      api: "the//api//here",
      query: "",
      key: "?api-key=XXXXXX"
    };

    this.handleMenu = this.handleMenu.bind(this)
    this.handleCategory = this.handleCategory.bind(this)
  }

  handleMenu() {
    this.setState({
      isMenuOpen: !state.isMenuOpen
    })
  }

  handleCategory(event) {
    this.setState({
      query: event.target.getAttribute('data-facet')
    })
  }

  componentDidMount() {
    fetch(this.state.api + this.state.query  +".json" + this.state.key)
      .then(response => {
        if (response.ok) {
          return response.json();
        } else {
          throw new Error('Oops')
        }
      })
      .then(data => this.setState({ results: data.results, isLoading: false}))
      .catch(error => this.setState({ error, isLoading: false }))
  }

  render() {
    const { results, isLoading, error } = this.state

    if (error) {
      return <div className="cards">{error.message}</div>
    }

    if (isLoading) {
      return <div className="cards">Loading...</div>;
    }

    return (
      <div className="wrapper">

        <div className="menu-trigger"><MaterialIcon icon="menu"/></div>
        <div className="menu">
          <ul>
            <li data-facet="arts" onClick={this.handleCategory}>Arts</li>
            <li data-facet="automobiles" onClick={this.handleCategory}>Automobiles</li>
            <li data-facet="books" onClick={this.handleCategory}>Books</li>
            <li data-facet="business" onClick={this.handleCategory}>Business</li>
            <li data-facet="fashion" onClick={this.handleCategory}>Fashion</li>
            <li data-facet="food" onClick={this.handleCategory}>Food</li>
            <li data-facet="health" onClick={this.handleCategory}>Health</li>
            <li data-facet="home" onClick={this.handleCategory}>Home</li>
          </ul>
        </div>

        <div className="cards">
          {results.slice(0, 10).map(result => (
            <div className="cards__card" key={result.title}>
              <a href={result.url} target="_blank"><h5>{result.title}</h5></a>
              <p>{result.abstract}</p>
              <p className="small">Published {Moment(result.published_date).format('MMMM Do YYYY, h:mm a')}</p>
            </div>
          ))}
        </div>
      </div>
    );
  }

}

export default App

1 Ответ

0 голосов
/ 31 октября 2019

Для повторного рендеринга компонента с обновленными данными необходимо обновить переменную состояния.

Предполагается, что вы храните свои данные в this.state.results - Однако вы не обновляете этосостояние в handleCategory.

Есть несколько вещей, которые вы можете сделать:

  • абстрагировать ваш вызов извлечения, чтобы его можно было многократно использовать
  • использовать функции стрелок, чтобы избавиться от привязок в конструкторе
  • избавиться от жизненного цикла componentWillUpdate, поскольку он избыточен
class App extends Component {
  constructor(props) {
    super(props);

    this.state = {
      isLoading: false,
      results: [],
      error: null,
    };
  }

  fetchData = (url, query, key) => {
    fetch(`the/api/${url}${query}.json?api-key${key}`)
      .then(res => res.ok && res.json())
      .then(data => this.setState({ results: data.results, isLoading: false }))
      .catch(error => this.setState({ error, isLoading: false }));
  }

  componentDidMount() {
    fetchData('api_url', 'all', 'key_here');
  }

  handleCategory = (e) => {
    const cat = e.target.getAttribute('data-facet');
    fetchData('api_url', cat, 'key_here');
  }

  render() {
    const { isLoading, results, error } = this.state;

    if (isLoading) {
      return <div className="loading-icon"></div>
    }

    if (error) {
      return <div className="error"></div>    
    }

    return (
      <div className="wrapper">
        <button data-facet="arts" onClick={this.handleCategory}>Arts</button>
        {results.map(res => ...)}
      </div>
    );
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...