在React中对API fetch onClick进行更改

问题描述 投票:0回答:1

我正在对UI进行原型设计并从React中的API中获取数据:

  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
json reactjs rest
1个回答
0
投票

为了使组件使用更新后的数据重新呈现,您需要更新状态变量。

假设您将数据存储在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>
    );
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.