Json 对API fetch onClick in React进行更改

Json 对API fetch onClick in React进行更改,json,reactjs,rest,Json,Reactjs,Rest,我正在制作UI原型,并从API获取数据,如React中所示: componentWillUpdate() { fetch(this.state.api + this.state.query +".json" + this.state.key) .then(response => { if (response.ok) { return response.json(); } else { thro

我正在制作UI原型,并从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')
    })
  }
如何让UI更新和显示来自新类别的数据?这几天来我一直在用我的头撞这个。我已经编写了几种成功更新获取字符串的方法,但是没有一种方法强制组件重新呈现和显示新项。谢谢


使用完整的组件代码更新:

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
import React,{Component}来自“React”
从“时刻”导入时刻
从“材质图标”导入MaterialIcon
导入“../assets/styles/app.scss”
类应用程序扩展组件{
建造师(道具){
超级(道具);
此.state={
错误:null,
孤岛加载:false,
isMenuOpen:错,
结果:[],
api://api//here“,
查询:“”,
密钥:“?api密钥=XXXXXX”
};
this.handleMenu=this.handleMenu.bind(this)
this.handleCategory=this.handleCategory.bind(this)
}
handleMenu(){
这是我的国家({
isMenuOpen:!state.isMenuOpen
})
}
手分类(事件){
这是我的国家({
查询:event.target.getAttribute('data-facet')
})
}
componentDidMount(){
fetch(this.state.api+this.state.query+“.json”+this.state.key)
。然后(响应=>{
if(response.ok){
返回response.json();
}否则{
抛出新错误('Oops')
}
})
.then(data=>this.setState({results:data.results,isLoading:false}))
.catch(error=>this.setState({error,isLoading:false}))
}
render(){
const{results,isLoading,error}=this.state
如果(错误){
返回{error.message}
}
如果(孤岛加载){
返回装载。。。;
}
返回(
  • arts
  • 汽车
  • books
  • business
  • fashion
  • food
  • health
  • home
{results.slice(0,10).map(result=>( {result.abstract}

已发布{Moment(result.Published_date).format('MMMM Do YYYY,h:mm a')}

))} ); } } 导出默认应用程序
为了让组件使用更新的数据重新呈现,您需要更新状态变量

假设您将数据存储在
this.state.results
-但是,您不会在
handleCategory
中更新此状态

您可以做以下几件事:

  • 提取提取调用,以便可重用
  • 使用箭头函数消除构造函数中的绑定
  • 摆脱
    组件将更新
    生命周期,因为它是冗余的
类应用程序扩展组件{
建造师(道具){
超级(道具);
此.state={
孤岛加载:false,
结果:[],
错误:null,
};
}
fetchData=(url、查询、键)=>{
fetch(`the/api/${url}${query}.json?api key${key}`)
。然后(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;
如果(孤岛加载){
返回
}
如果(错误){
返回
}
返回(
艺术类
{results.map(res=>…)}
);
}
}

您能告诉我为什么在componentWillUpdate而不是componentDidMount中调用api吗?还可以共享完整的代码,以便我检查。我已经更新了问题,包括完整的代码。我把组件willupdate()
取进来只是因为我在胡闹。它已在
componentDidMount
中运行。您的性能不会很好,因为您正在li标签中使用多个相同的单击功能。我想你应该循环这个,并通过id/value进行处理。你能在沙盒中共享吗?这样我就可以改进了。很高兴!我该怎么做?你是说做个密码笔什么的?太好了,谢谢。为了澄清,在
componentDidMount
阶段,我是否应该将api\u url、cat和key硬编码为第一次加载的默认值?当然。您可以回退到默认值,以便在
cDM
中不必使用params调用。ES6有默认参数,所以您可以只执行
fetchData=(url='foo',query='all',key='0')=>…