Skip to content
On this page

Class

js
import React, { Component } from 'react';

// 定义一个通用的数据获取组件,它通过render prop来提供数据获取功能
class DataFetcher extends Component {
  constructor(props) {
    super(props);
    this.state = {
      data: null, // 存储获取到的数据
      isLoading: true, // 标识是否正在获取数据
      error: null, // 存储错误信息(如果有)
    };
  }

  // 组件挂载后进行数据获取
  componentDidMount() {
    this.fetchData()
      .then(data => this.setState({ data, isLoading: false }))
      .catch(error => this.setState({ error, isLoading: false }));
  }

  // 模拟一个数据获取的方法
  fetchData = () => {
    // 假设使用Promise模拟异步操作,实际中这里会是如fetch()这样的API调用
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        const data = { message: "这是获取到的数据" };
        // 模拟可能出现的错误
        if (Math.random() > 0.8) {
          reject("数据获取失败");
        } else {
          resolve(data);
        }
      }, 1000);
    });
  };

  render() {
    // 从props中获取render prop函数
    const { render } = this.props;
    const { data, isLoading, error } = this.state;

    // 使用render prop,将数据、状态和必要的函数通过children传递
    return render({
      data,
      isLoading,
      error,
      refetch: this.fetchData, // 提供一个重新获取数据的方法
    });
  }
}

// 使用DataFetcher的例子
const App = () => (
  <div>
    <h1>使用Render Prop获取数据示例</h1>
    <DataFetcher
      // 传递render prop函数
      render={({ data, isLoading, error, refetch }) => (
        <div>
          {isLoading ? (
            <p>加载中...</p>
          ) : error ? (
            <p onClick={() => refetch()}>数据获取失败,点击重试</p>
          ) : (
            <div>
              <p>{data.message}</p>
            </div>
          )}
        </div>
      )}
    />
  </div>
);

export default App;

函数组件 + Hooks

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

// 使用函数组件和Hooks改写的DataFetcher
const DataFetcher = ({ render }) => {
  const [data, setData] = useState(null); // 用于存储获取到的数据
  const [isLoading, setIsLoading] = useState(true); // 标识是否正在获取数据
  const [error, setError] = useState(null); // 存储错误信息(如果有)

  // 使用useEffect替代componentDidMount进行数据获取
  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await fetch('https://api.example.com/data'); // 模拟数据获取
        const result = await response.json();
        setData(result);
      } catch (error) {
        setError(error.message);
      } finally {
        setIsLoading(false);
      }
    };

    fetchData();
  }, []); // 空依赖数组意味着这个effect仅在组件挂载时运行一次

  // 使用render prop传递数据和状态
  return render({ data, isLoading, error, refetch: fetchData });
};

// 使用DataFetcher的例子
const App = () => (
  <div>
    <h1>使用Render Prop获取数据示例</h1>
    <DataFetcher
      render={({ data, isLoading, error, refetch }) => (
        <div>
          {isLoading ? (
            <p>加载中...</p>
          ) : error ? (
            <p onClick={() => refetch()}>数据获取失败,点击重试</p>
          ) : (
            <div>
              <p>{data.message}</p>
            </div>
          )}
        </div>
      )}
    />
  </div>
);

export default App;