写点什么

如何在渲染之前等待 Axios 数据?

用户头像
DisonTangor
关注
发布于: 刚刚

【转自 CodeWithNico 的《How to wait for Axios data before you render it?》翻译】


使用 Axios 获取数据很容易,但是渲染它~哎哟~


你可能知道如何用 Axios 获取数据,但你如何在 React 中渲染它?


也许你尝试过 await 在渲染函数中使用类似的方法让 React 在渲染之前等待你的请求。但是,当您执行以下操作时:


async render() {    return <>{await axios.get(..)}</>}
复制代码
在 render() 中等待

你会得到这样的错误:

在 render() 中使用 await 时出错


为什么?因为async操作使render函数返回一个Promise,它是一个对象,而 React 不知道渲染对象。


那么,你如何让 React 在渲染之前等待你的函数呢?


嗯,答案是:假装😏

渲染前等待 Axios

这样做有一个获取方法,它总是相同的:


  1. 以“加载模式”启动你的组件

  2. *当您的组件“安装”时*执行请求。

  3. 请求完成后,保存您的数据并关闭“加载模式”。

  4. 确保当您的组件处于“加载模式”时,在渲染函数中显示微调器或加载文本。如果没有,则显示您的数据。

你如何在代码中做到这一点?

看看这个简单的 React 应用程序,它获取有关单个 Pokémon 的数据并显示其名称和图片:



示例代码可以在这里找到


这是实现:


function App() {    const [isLoading, setLoading] = useState(true);    const [pokemon, setPokemon] = useState();
useEffect(() => { axios.get("https://pokeapi.co/api/v2/pokemon/4").then(response => { setPokemon(response.data); setLoading(false); }); }, []);
if (isLoading) { return <div className="App">Loading...</div>; }
return ( <div className="App"> <h1>{pokemon.name}</h1> <img alt={pokemon.name} src={pokemon.sprites.front_default} /> </div> );}
复制代码


加载、获取和显示!


这如何转化为我们的食谱?

1) 在“加载模式”下启动你的组件

这样你就可以在“加载模式”下启动你的组件


通过“Loading...”文本的条件渲染和使用 useState,我们完成了组件的“加载模式”状态。


**为什么我们使用 useState 而不是简单的 const?**因为我们想让 App 组件在渲染之间记住这个值!


第一个渲染在浏览器中显示“正在加载...”。

2) 当您的组件“安装”时执行请求

安装 → “渲染后” → 使用 useEffect 完成


useEffect 接收一个将在 DOM(浏览器显示的内容)更新后调用的函数。这里我们告诉 axios 从 PokeApi 获取 Charmander 数据。


axios.get 是异步执行的,所以没有任何改变。

3) 请求完成后,保存您的数据并关闭“加载模式”


请求完成后,我们使用setLoading和更新组件的状态setPokemon


两个调用都会更新状态:


  • setPokemon更新pokemon:从undefinedresponse.data

  • setLoading更新isLoading:从truefalse


所以......有 2 个渲染!🤯


第二渲染(通过触发 setPokemon)不会做任何事情在浏览器中,因为 isLoadingtrue→组件返回“正在加载...”一次。


第三次渲染(由 触发 setLoading)将在浏览器中显示 小火龙(Charmander)!因为这个时间isLoadingfalse,所以我们到达了 pokemon 最终渲染的函数的末尾。


不熟悉钩子?

嘿!是 2020 年,你应该!😂


export default class App extends Component {    constructor(props) {        super(props);        this.state = { isLoading: true, pokemon: undefined };    }
componentDidMount() { console.debug("After mount! Let's load data from API..."); axios.get("https://pokeapi.co/api/v2/pokemon/4").then(response => { this.setState({ pokemon: response.data }); this.setState({ isLoading: false }); }); }
render() { const { isLoading, pokemon } = this.state;
if (isLoading) { return <div className="App">Loading...</div>; }
return ( <div className="App"> <h1>{pokemon.name}</h1> <img alt={pokemon.name} src={pokemon.sprites.front_default} /> </div> ); }}
复制代码


CodeSandbox 中使用类组件的代码

发布于: 刚刚阅读数: 2
用户头像

DisonTangor

关注

怀揣一个武侠梦的男孩 2020.07.29 加入

还未添加个人简介

评论

发布
暂无评论
如何在渲染之前等待 Axios 数据?