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

时间:2016-05-29 12:17:08

标签: javascript ajax api reactjs refactoring

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

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 组件中。

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

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返回res.json()作为承诺。

我尝试在外部函数中包装fetchProfiles,也是在新的承诺中!但没有任何作品!我在这做错了什么?请帮助解决这个问题。

3 个答案:

答案 0 :(得分:4)

您需要返回fetch(url)本身,这样您就会返回一个承诺,然后您可以使用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() );
}

答案 1 :(得分:1)

我解决这个问题的方法是返回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
          });
        });
    }

这现在有效!!

答案 2 :(得分:0)

我曾经做过一个类似的应用程序,将API调用与上下文分离(我使用上下文API btw),而不是返回fetch函数并处理上下文的异步调用,我处理了API声明的函数上的所有内容并且在上下文中仅接收到结果,这似乎稍微复杂一点,但是它简化了上下文中的数据处理以及另一侧的所有数据获取登录,我也使用axios进行API调用,但是很容易交换抓取一个(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
  });
}