React:如何将 ajax api 调用移动到单独的组件中?

React: How do I move my ajax api call into a separate component?

这是一个运行良好的典型容器组件:

const API = 'https://randomuser.me/api/?results=5';
class App extends Component {

    constructor(props) {
      super(props);
      this.state = { profiles: [] };
    }

    componentDidMount() {
      this.fetchProfiles();
    }

    fetchProfiles() {
      let url = API;
      fetch(url)
        .then( (res) => res.json() )
        .then( (data) => {
          let results = data.results;
          this.setState({
            profiles: results 
          });
        })
        .catch( (error) => console.log('Oops! . There Is A Problem', error) );
    }

    render() {
      // rendering child component here
    }
}

export default App;

我现在要做的是将 fetchProfiles 函数移动到单独的 api 组件中。

所以我在项目的 api 文件夹中创建了一个 profiles.js 文件:

const API = 'https://randomuser.me/api/?results=5';

export function fetchProfiles() {
  let url = API;
  fetch(url)
  .then( (res) => res.json() );
}

现在我的主要组件导入它并像这样使用它:

import { fetchProfiles } from '../api/profiles.js';


const API = 'https://randomuser.me/api/?results=5';
class App extends Component {

    constructor(props) {
      super(props);
      this.state = { profiles: [] };
    }

    componentDidMount() {
      fetchProfiles.then((data) => {
        let results = data.results;
          this.setState({
            profiles: results 
          });
      });
    }

  // render call etc

但是当我 运行 像这样在 componentDidMount 中调用时,我得到这个错误:Uncaught TypeError: _profiles.fetchProfiles.then is not a function。我正在尝试与 then 链接,因为 fetch api returns res.json() 作为承诺。

我尝试将 fetchProfiles 包装在一个外部函数中,也在一个新的承诺中!但是没有任何效果!我在这里做错了什么?请帮助进行此重构。

我解决这个问题的方法是 return fetch(url) 本身:

const API = 'https://randomuser.me/api/?results=5';

export function fetchProfiles() {
    let url = API;
    return fetch(url)
      .then( (response) => response.json() );
}

然后在容器组件中:

    componentDidMount() {
      fetchProfiles()
        .then( (data) => {
          let results = data.results;
          this.setState({
            profiles: results
          });
        });
    }

现在可以使用了!!

你需要 return fetch(url) 本身,所以你会 return 一个承诺,然后你可以使用 then 方法:

const API = 'https://randomuser.me/api/?results=5';

export function fetchProfiles() {
  let url = API;

  // return the promise itself
  return fetch(url).then( (res) => res.json() );
}

我曾经做过一个类似的应用程序,我将 API 调用与上下文分开(顺便说一句,我使用了上下文 API),而不是返回获取函数并处理上下文中的异步调用,我处理了在 API 上声明的函数上的所有内容,而在上下文中只收到了结果,这似乎有点复杂,但它简化了上下文中的数据处理和另一个上的所有数据获取登录一方面,我还在 API 调用中使用了 axios,但它很容易与 fetch 调用交换(axios 处理更好的错误,例如处理超时或服务不可用)

在 profiles.js 上:

import axios from 'axios';

const API = 'https://randomuser.me/api/?results=5';    

export const fetchProfiles = async () => {
    let url = API;
    try{
      const response = await axios.get(url)
      const data = response.data
      return data
    }catch(error) {
      console.log('failed to fetch Profiles')
      throw Error(error)
    }
}

上下文:

import { fetchProfiles} from "../API/profiles";

const getProfiles = async () =>{
  const result = await fetchProfiles();
  this.setState({
    profiles: result
  });
}