如何在 React Hook 中请求数据?

斜体样式本文大致的翻译了这篇文章

本文将向你展示如何通过 react 的 state 和 effect hook 获取数据。本文将使用 Hacker News API 获取科技类的热门文章,带你实现自定义的 react hook 来获取数据。

react hook 之获取数据

import React, {
    useState } from 'react';
 
function App() {
   
  const [data, setData] = useState({
    hits: [] });
 
  return (
    <ul>
      {
   data.hits.map(item => (
        <li key={
   item.objectID}>
          <a href={
   item.url}>{
   item.title}</a>
        </li>
      ))}
    </ul>
  );
}
 
export default App;

App 组件做的一件事就是显示文章列表(hits = Hacker News 文章)。useState 为函数组件提供状态和状态更新功能,它负责为 App 组件管理数据的局部状态。初始状态是 {hits: []},hits 为空数组。此时没有任何地方修改这个状态。

接下来使用 axios 这个库来获取数据,如果你还未安装,可以通过 npm install axios -S 安装一下。

import React, {
    useState, useEffect } from 'react';
import axios from 'axios';
 
function App() {
   
  const [data, setData] = useState({
    hits: [] });
 
  useEffect(async () => {
   
    const result = await axios(
      'https://hn.algolia.com/api/v1/search?query=redux',
    );
 
    setData(result.data);
  });
 
  return (
    <ul>
      {
   data.hits.map(item => (
        <li key={
   item.objectID}>
          <a href={
   item.url}>{
   item.title}</a>
        </li>
      ))}
    </ul>
  );
}
 
export default App;

在 effect hook useEffect 里通过 axios 请求数据,并通过 state hook 的更新函数 setData 来将请求到的数据设置到组件的局部状态 data 里。
但是这时运行起来的代码应该会陷入死循环,因为组件挂载后会运行 useEffect 里的 axios 代码获取数据,然后更新状态 data,继而引发组件更新,而组件更新后 useEffect 又会再次运行,再次获取数据,再次触发组件更新。如此反复,进入死循环。我们只希望在组件挂载时请求一次数据,后续不再触发。我们可以给 useEffect 的第二个参数传入一个空数组,如下:

import React, {
    useState, useEffect } from 'react';
import axios from 'axios';
 
function App() {
   
  const [data, setData] = useState({
    hits: [] });
 
  useEffect(async () => {
   
    const result = await axios(
      'https://hn.algolia.com/api/v1/search?query=redux',
    );
 
    setData(result.data);
  }, []);
 
  return (
    <ul>
      {
   data.hits.map(item => (
        <li key={
   item.objectID}>
          <a href={
   item.url}>{
   item.title}</a>
        </li>
      ))}
    </ul>
  );
}
 
export default App;

第二个参数是一个数组,用来定义该 useEffect 依赖的变量,只要依赖的变量发生变化,这个 hook 就会再次运行。而如果这个数组是一个空数组,那么这个 hook 不会再组件更新时运行,因为它不依赖任何变量。
到这里还有最后一个问题,我们用了 async / await 来获取数据,按照标准 async 函数会返回一个隐式的 promise。然而,effect hook 不能返回任何任何东西,也不能返回函数。所以你会看到一个提示 Warning: An effect function must not return anything besides a function, which is used for clean-up. 所以直接在 useEffect 里使用 async 函数是不允许的,改下代码,如下:

import React, {
    useState, useEffect } from 'react';
import axios from 'axios';
 
function App() {
   
  const [data, setData] = useState({
    hits: [] });
 
  useEffect(() => {
   
    const fetchData = async () => {
   
      const result = await axios(
        'https://hn.algolia.com/api/v1/search?query=redux',
      );
 
      setData(result.data);
    };
 
    fetchData();
  }, []);
 
  return (
    <ul>
      {
   data.hits.map(item => (
        <li key={
   item.objectID}>
          <a href={
   item.url}>{
   item.title}</a>
        </li>
      ))}
    </ul>
  );
}
 
export default App;

以上就是在 react hook 里获取数据的简单示例。如果你对错误处理、loading 状态以及如何在 form 表单中获取数据和封装一个可复用的数据获取 hook 感兴趣的话,可以继续阅读下去。

如何自动或手动触发获取数据

现在通过这个组件已经能获取数据了,可是如何通过数据关键词来搜索想要的文章呢。我们添加一个输入框,用于输入搜索关键词,为此需要引入新的状态:

import React, {
    Fragment, useState, useEffect } from 'react';
import axios from 'axios';
 
function App() {
   
  const [data, setData] = useState({
    hits: [] });
  const [query, setQuery] = useState('redux');
 
  useEffect(() => {
   
    const fetchData = async () => {
   
      const result = await axios(
        'https://hn.algolia.com/api/v1/search?query=redux',
      );
 
      setData(result.data);
    };
 
    fetchData();
  }, []);
 
  return (
    <Fragment>
      <input
        type="text"
        value={
   query}
        onChange={
   event => setQuery(event.target.value)}
      />
      <ul>
        {
   data.hits.map(item => (
          <li key={
   item.objectID}>
            <a href={
   item.url}>{
   item.title}</a>
          </li>
        ))}
      </ul>
    </Fragment>
  );
}
 
export default App;

此时两个状态是相互独立的,但是我们想把他们结合起来,搜索想要的文章,做如下改动:

...
 
function App() {
   
  const 
  • 5
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值