React AJAX

React 组件本身不负责取数据,真实应用的数据通常来自后端接口,需要通过 AJAX 异步请求获得。AJAX 属于"副作用",要放在组件挂载完成后执行,再配合加载中、失败、空数据等状态渲染,页面体验才完整。

请求应该放在哪里

不要在 render 里直接发请求,否则每次渲染都会重复请求。类组件放在 componentDidMount 中;函数组件放在 useEffect 中,并传入空依赖数组 [],让请求只在挂载后执行一次。

fetch 基础用法(类组件)

fetch 是浏览器内置 API,返回 Promise,先 res.json() 解析再写入 state:

import { Component } from 'react'
class UserList extends Component {
  state = { users: [] }
  componentDidMount() {
    fetch('https://api.example.com/users')
      .then(res => res.json())
      .then(data => this.setState({ users: data }))
      .catch(err => console.error('请求失败', err))
  }
  render() {
    return (
      <ul>
        {this.state.users.map(u => <li key={u.id}>{u.name}</li>)}
      </ul>
    )
  }
}

处理加载中、失败与空数据

请求是异步的,页面应先用 loading 状态过渡,拿到数据再渲染列表;失败进 catch 提示,无数据则渲染空状态:

class UserList extends Component {
  state = { loading: true, users: [] }
  componentDidMount() {
    fetch('https://api.example.com/users')
      .then(res => res.json())
      .then(data => this.setState({ users: data, loading: false }))
      .catch(() => this.setState({ loading: false }))
  }
  render() {
    if (this.state.loading) {
      return <p>加载中...</p>
    }
    if (this.state.users.length === 0) {
      return <p>暂无用户数据</p>
    }
    return (
      <ul>
        {this.state.users.map(u => <li key={u.id}>{u.name}</li>)}
      </ul>
    )
  }
}

函数组件:useEffect 中请求

函数组件把请求写进 useEffect,第二个参数传空数组 [],表示只在挂载后执行一次:

import { useEffect, useState } from 'react'
function UserList() {
  const [users, setUsers] = useState([])
  useEffect(() => {
    fetch('https://api.example.com/users')
      .then(res => res.json())
      .then(data => setUsers(data))
      .catch(err => console.error('请求失败', err))
  }, [])
  return (
    <ul>
      {users.map(u => <li key={u.id}>{u.name}</li>)}
    </ul>
  )
}

注意 useEffect 里的函数不能直接 async,一般再包一层内部函数调用。

使用 axios 发送请求

axios 是流行的 HTTP 库,先安装 npm install axios。它自动把响应解析成 JSON,也支持超时与拦截器,写起来更简洁:

import axios from 'axios'
componentDidMount() {
  axios.get('https://api.example.com/users')
    .then(res => this.setState({ users: res.data })) // 数据在 res.data
    .catch(err => console.error('请求失败', err))
}

上面的片段需放进类组件;函数组件中同样把它写在 useEffect 里。

小结:React AJAX 是固定套路——挂载后发请求(componentDidMount 或 useEffect+[])、用 loading 过渡、失败给提示;fetch 足够入门,规模大一点的项目通常换用 axios。

笔记加载中…