在 response js 中如何正确地进行 API 调用?

我最近从 Angular 转到了 ReactJ。我使用 jQuery 进行 API 调用。我有一个 API,它返回一个随机用户列表,将打印在一个列表中。

我不知道如何编写我的 API 调用。这方面的最佳实践是什么?

我尝试了以下方法,但是没有得到任何输出。如果有必要,我愿意实现替代 API 库。

下面是我的代码:

import React from 'react';


export default class UserList extends React.Component {
constructor(props) {
super(props);
this.state = {
person: []
};
}


UserList(){
return $.getJSON('https://randomuser.me/api/')
.then(function(data) {
return data.results;
});
}


render() {
this.UserList().then(function(res){
this.state = {person: res};
});
return (
<div id="layout-content" className="layout-content-wrapper">
<div className="panel-list">
{this.state.person.map((item, i) =>{
return(
<h1>{item.name.first}</h1>
<span>{item.cell}, {item.email}</span>
)
})}
<div>
</div>
)
}
}
345259 次浏览

在这种情况下,您可以在 componentDidMount中执行 ajax 调用,然后更新 state

export default class UserList extends React.Component {
constructor(props) {
super(props);


this.state = {person: []};
}


componentDidMount() {
this.UserList();
}


UserList() {
$.getJSON('https://randomuser.me/api/')
.then(({ results }) => this.setState({ person: results }));
}


render() {
const persons = this.state.person.map((item, i) => (
<div>
<h1>{ item.name.first }</h1>
<span>{ item.cell }, { item.email }</span>
</div>
));


return (
<div id="layout-content" className="layout-content-wrapper">
<div className="panel-list">{ persons }</div>
</div>
);
}
}

我想让你看看复制版 Http://redux.js.org/index.html

他们有非常明确的方式来处理异步调用,即 API 调用,而不是使用 jQuery 的 API 调用,我想推荐使用 捡回来请求 npm 包,捡回来目前是支持现代浏览器,但垫片也可用于服务器端。

还有另一个令人惊奇的软件包 超级代理,它在提出 API 请求时有很多选项,并且非常容易使用。

你可能想看看 通量结构。我还建议检查 React-Redux 实现。把你的 API 电话放在你的行动中。它比把它们全部放在组件中要干净得多。

操作是一种帮助器方法,您可以调用它来更改应用程序状态或执行 api 调用。

渲染功能应该是纯粹的,这意味着它只使用状态和道具渲染,从来没有尝试修改状态在渲染,这通常会导致丑陋的错误,并显着降低性能。如果在 React 应用程序中将数据获取和呈现问题分开,这也是一个很好的观点。我建议你阅读这篇文章,它很好地解释了这个想法。https://medium.com/@learnreact/container-components-c0e67432e005#.sfydn87nm

这个讨论已经有一段时间了,@Alexander T 的回答为像我这样的新手提供了一个很好的指导。我将分享一些额外的诀窍,如何多次调用相同的 API 来刷新组件,我认为这可能是初学者经常遇到的问题。

componentWillReceiveProps(nextProps),来自 正式文件:

如果需要更新状态以响应道具更改(针对 例如,要重置它) ,可以比较 this. props 和 nextProps 以及 在此方法中使用 this.setState ()执行状态转换。

我们可以得出这样的结论: 这里是我们处理来自父组件的道具、 API 调用和更新状态的地方。

基于@Alexander T 的例子:

export default class UserList extends React.Component {
constructor(props) {
super(props);
this.state = {person: []};
}


componentDidMount() {
//For our first load.
this.UserList(this.props.group); //maybe something like "groupOne"
}


componentWillReceiveProps(nextProps) {
// Assuming parameter comes from url.
// let group = window.location.toString().split("/")[*indexParameterLocated*];
// this.UserList(group);
   

// Assuming parameter comes from props that from parent component.
let group = nextProps.group; // Maybe something like "groupTwo"
this.UserList(group);
}


UserList(group) {
$.getJSON('https://randomuser.me/api/' + group)
.then(({ results }) => this.setState({ person: results }));
}


render() {
return (...)
}
}

更新

componentWillReceiveProps()将被弃用。

在生命周期中只有 一些方法(都在 医生中) ,我认为它们与在一般情况下部署 API 有关: enter image description here

参考上图:

  • componentDidMount()中部署 API

    在这里调用 API 的正确场景是这个组件的内容(来自 API 的响应)将是静态的,componentDidMount()只在组件安装时触发一次,甚至新的道具从父组件传递或者有操作来引导 re-rendering
    该组件确实检查 重新渲染的差异,但不检查 重新上马的差异。
    引自 医生:

如果需要从远程端点加载数据,这是一个很好的位置 实例化网络请求。


  • static getDerivedStateFromProps(nextProps, prevState)中部署 API

我们应该注意到有两种 组件更新setState() 电流分量没有触发这种方法,但重新渲染或新的道具从 父组件。 我们可以发现这种方法也火灾,而安装。

这是部署 API 如果我们希望使用当前组件作为模板,并且用于进行 API 调用的新参数是来自父组件的支持的合适位置。
我们从 API 收到一个不同的响应,并在这里返回一个新的 state来更改这个组件的内容。

例如:
我们在父组件中有一个针对不同车辆的下拉列表,这个组件需要显示所选车辆的详细信息。


  • componentDidUpdate(prevProps, prevState)中部署 API

static getDerivedStateFromProps()不同,此方法在每次呈现后立即调用,但初始呈现除外。我们可以在一个组件中使用 API 调用和呈现差异。

扩展前面的例子:
显示 Car 详细信息的组件可能包含一系列这款车的列表,如果我们想检查2013年的生产车,我们可以点击或选择或... 列表项引导第一个 setState()来反映这个组件中的这种行为(例如突出显示列表项) ,在下面的 componentDidUpdate()中,我们发送带有新参数(状态)的请求。得到响应后,我们 setState()再次渲染不同内容的汽车细节。为了防止下面的 componentDidUpdate()导致无限循环,我们需要在这个方法的开头利用 prevState来比较状态,以决定是否发送 API 并呈现新内容。

这种方法真的可以像 static getDerivedStateFromProps()一样使用道具,但是需要利用 prevProps来处理 props的变化。我们需要与 componentDidMount()合作来处理初始 API 调用。

引自 医生:

... 这也是一个很好的地方,做网络请求,只要你 比较目前的道具和以前的道具。

反应 V16文档的这一部分将回答您的问题,请继续阅读关于 Component entDidMount ()的内容:

Component entDidMount ()

在组件被调用之后立即调用 Component entDidMount () 需要 DOM 节点的初始化应该放在这里。如果 需要从远程端点加载数据,这是一个很好的地方 实例化网络请求。这种方法是一个很好的设置位置 任何订阅。如果你这样做,不要忘记退订 组件 WillUnmount ()。

正如你所看到的,组件被认为是进行 API 呼叫的最佳位置和周期,也是访问节点的最佳位置,这意味着这个时候可以安全地进行调用、更新视图或者在文档准备好时可以做的任何事情,如果你正在使用 jQuery,它应该以某种方式提醒你 document.ready ()函数,在该函数中,你可以确保一切都准备好了,可以在代码中进行任何操作..。

使用 componentDidMount中的 fetch方法更新状态:

componentDidMount(){
fetch('https://randomuser.me/api/')
.then(({ results }) => this.setState({ person: results }));
}

1)你可以使用 F蚀刻原料药从端点获取数据:

为用户获取所有 Github休息的示例

  /* Fetch GitHub Repos */
fetchData = () => {


//show progress bar
this.setState({ isLoading: true });


//fetch repos
fetch(`https://api.github.com/users/hiteshsahu/repos`)
.then(response => response.json())
.then(data => {
if (Array.isArray(data)) {
console.log(JSON.stringify(data));
this.setState({ repos: data ,
isLoading: false});
} else {
this.setState({ repos: [],
isLoading: false
});
}
});
};

2)其他选择是 Axios

通过使用公理,您可以省去传递 对. json ()方法的 http 请求 你所期望的对象。

  import axios from "axios";


/* Fetch GitHub Repos */
fetchDataWithAxios = () => {


//show progress bar
this.setState({ isLoading: true });


// fetch repos with axios
axios
.get(`https://api.github.com/users/hiteshsahu/repos`)
.then(result => {
console.log(result);
this.setState({
repos: result.data,
isLoading: false
});
})
.catch(error =>
this.setState({
error,
isLoading: false
})
);
}

现在,您可以选择使用 componentDidMount中的任何一种策略来获取数据

class App extends React.Component {
state = {
repos: [],
isLoading: false
};


componentDidMount() {
this.fetchData ();
}

同时,可以在加载数据时显示进度条

   {this.state.isLoading && <LinearProgress />}

一种干净的方法是使用 Try/catch 函数组件内部进行异步 API 调用。

当我们调用 API 时,会收到一个响应。然后我们对其应用 JSON 方法,将响应转换为 JavaScript 对象。然后,我们从该响应对象中只获取名为“ result”(data.result)的子对象。

一开始,我们将状态中的“ userList”定义为一个空数组。一旦我们进行 API 调用并从该 API 接收数据,我们就使用 SetState 方法将“结果”分配给 userList。

在呈现函数中,我们告诉 userList 将来自状态。由于 userList 是一个对象数组,我们通过它来映射,以显示每个对象“用户”的图片、名称和电话号码。为了检索这些信息,我们使用点表示法(例如 user.phone)。

注意 : 根据您的 API,您的响应可能看起来不同。记录整个“响应”,看看需要从中获取哪些变量,然后在 setState 中分配它们。

UserList.js

import React, { Component } from "react";


export default class UserList extends Component {
state = {
userList: [], // list is empty in the beginning
error: false
};


componentDidMount() {
this.getUserList(); // function call
}


getUserList = async () => {
try { //try to get data
const response = await fetch("https://randomuser.me/api/");
if (response.ok) { // ckeck if status code is 200
const data = await response.json();
this.setState({ userList: data.results});
} else { this.setState({ error: true }) }
} catch (e) { //code will jump here if there is a network problem
this.setState({ error: true });
}
};


render() {
const { userList, error } = this.state
return (
<div>
{userList.length > 0 && userList.map(user => (
<div key={user}>
<img src={user.picture.medium} alt="user"/>
<div>
<div>{user.name.first}{user.name.last}</div>
<div>{user.phone}</div>
<div>{user.email}</div>
</div>
</div>
))}
{error && <div>Sorry, can not display the data</div>}
</div>
)
}}

外部 API 调用的最佳位置和实践是 React LifCycle 方法 Component entDidMount (),在执行 API 调用之后,您应该更新本地状态以触发新的 提交()方法调用,然后更新的本地状态的更改将应用于组件视图。

作为 React 中 首字母缩写外部数据源调用的其他选项,指向类的 构造函数()方法。构造函数是初始化组件对象实例时执行的第一个方法。您可以在 高阶元件的文档示例中看到这种方法。

方法 组件 WillMount ()()不应该用于外部 API 调用,因为它们将被弃用。您可以看到 给你的常见原因,为什么这个方法将被弃用。

无论如何,你必须 永远不要使用 rend()方法或从 rend()直接调用的方法作为一个外部 API 调用点。如果你这样做你的 申请会被拒绝

也可以在函数组件中使用 用钩子取数据

使用 api 调用的完整示例: https://codesandbox.io/s/jvvkoo8pq3

第二个例子: https://jsfiddle.net/bradcypert/jhrt40yv/6/

const Repos = ({user}) => {
const [repos, setRepos] = React.useState([]);


React.useEffect(() => {
const fetchData = async () => {
const response = await axios.get(`https://api.github.com/users/${user}/repos`);
setRepos(response.data);
}


fetchData();
}, []);


return (
<div>
{repos.map(repo =>
<div key={repo.id}>{repo.name}</div>
)}
</div>
);
}


ReactDOM.render(<Repos user="bradcypert" />, document.querySelector("#app"))

对于支持取消、拦截等操作的 api 请求,使用公理是非常好的。除了公理,我还使用反应还原来管理状态和还原故事/还原思想的副作用。

作为对 Oleksandr T 优秀答案的补充/更新:

  • 如果使用 类组件,后端调用应该发生在 componentDidMount中。
  • 如果使用 钩子,则应使用 效果挂钩效果挂钩

例如:

import React, { useState, useEffect } from 'react';
   

useEffect(() => {
fetchDataFromBackend();
}, []);


// define fetchDataFromBackend() as usual, using Fetch API or similar;
// the result will typically be stored as component state

进一步阅读:

您必须为 API 调用尝试“ axios”库。 而不是直接使用 jQuery。

谢谢。