AJAX and APIs

如何在 React 中发起 AJAX 请求?

在 React 开发中,你能使用任何你喜欢的 AJAX 库,比如社区比较流行的 AxiosjQuery AJAX,或者是浏览器内置的 window.fetch

应该在 React 组件的哪个生命周期函数中发起 AJAX 请求?

我们推荐你在 componentDidMount 这个生命周期函数中发起 AJAX 请求。这样做你可以拿到 AJAX 请求返回的数据并通过 setState 来更新组件。

示例:使用 AJAX 请求结果去改变组件内部 state

下面这个组件演示了如何在 componentDidMount 中发起 AJAX 请求去更新组件的 state 。

示例 API 返回如下的 JSON 对象:

  1. {
  2. "items": [
  3. { "id": 1, "name": "Apples", "price": "$2" },
  4. { "id": 2, "name": "Peaches", "price": "$5" }
  5. ]
  6. }
  1. class MyComponent extends React.Component {
  2. constructor(props) {
  3. super(props);
  4. this.state = {
  5. error: null,
  6. isLoaded: false,
  7. items: []
  8. };
  9. }
  10. componentDidMount() {
  11. fetch("https://api.example.com/items")
  12. .then(res => res.json())
  13. .then(
  14. (result) => {
  15. this.setState({
  16. isLoaded: true,
  17. items: result.items
  18. });
  19. },
  20. // 注意:需要在此处处理错误
  21. // 而不是使用 catch() 去捕获错误
  22. // 因为使用 catch 去捕获异常会掩盖掉组件本身可能产生的 bug
  23. (error) => {
  24. this.setState({
  25. isLoaded: true,
  26. error
  27. });
  28. }
  29. )
  30. }
  31. render() {
  32. const { error, isLoaded, items } = this.state;
  33. if (error) {
  34. return <div>Error: {error.message}</div>;
  35. } else if (!isLoaded) {
  36. return <div>Loading...</div>;
  37. } else {
  38. return (
  39. <ul>
  40. {items.map(item => (
  41. <li key={item.id}>
  42. {item.name} {item.price}
  43. </li>
  44. ))}
  45. </ul>
  46. );
  47. }
  48. }
  49. }

这里与 Hook 的实现相同:

  1. function MyComponent() {
  2. const [error, setError] = useState(null);
  3. const [isLoaded, setIsLoaded] = useState(false);
  4. const [items, setItems] = useState([]);
  5. // 注意:空的依赖数组 []
  6. // 表示这个 useEffect
  7. // 与 componentDidMount() 类似,只运行一次
  8. useEffect(() => {
  9. fetch("https://api.example.com/items")
  10. .then(res => res.json())
  11. .then(
  12. (result) => {
  13. setIsLoaded(true);
  14. setItems(result);
  15. },
  16. // 注意:需要在此处处理错误
  17. // 而不是使用 catch() 去捕获错误
  18. // 因为使用 catch 去捕获异常会掩盖掉组件本身可能产生的 bug
  19. (error) => {
  20. setIsLoaded(true);
  21. setError(error);
  22. }
  23. )
  24. }, [])
  25. if (error) {
  26. return <div>Error: {error.message}</div>;
  27. } else if (!isLoaded) {
  28. return <div>Loading...</div>;
  29. } else {
  30. return (
  31. <ul>
  32. {items.map(item => (
  33. <li key={item.id}>
  34. {item.name} {item.price}
  35. </li>
  36. ))}
  37. </ul>
  38. );
  39. }
  40. }