js에 API 호출을 수행하는 올바른 방법은 무엇입니까?


137

최근에 Angular에서 ReactJs로 옮겼습니다. API 호출에 jQuery를 사용하고 있습니다. 목록에 인쇄 할 임의의 사용자 목록을 반환하는 API가 있습니다.

API 호출을 작성하는 방법을 잘 모르겠습니다. 가장 좋은 방법은 무엇입니까?

다음을 시도했지만 출력이 없습니다. 필요한 경우 대체 API 라이브러리를 구현할 수 있습니다.

아래는 내 코드입니다.

import React from 'react';

export default class UserList extends React.Component {    
  constructor(props) {
    super(props);
    this.state = {
      person: []
    };
  }

  UserList(){
    return $.getJSON('https://randomuser.me/api/')
    .then(function(data) {
      return data.results;
    });
  }

  render() {
    this.UserList().then(function(res){
      this.state = {person: res};
    });
    return (
      <div id="layout-content" className="layout-content-wrapper">
        <div className="panel-list">
          {this.state.person.map((item, i) =>{
            return(
              <h1>{item.name.first}</h1>
              <span>{item.cell}, {item.email}</span>
            )
          })}
        <div>
      </div>
    )
  }
}

2
사용중인 상태 관리 라이브러리에 따라 다릅니다. 아무것도 사용하지 않으면 API 호출을 별도의 파일로 이동하고 componentDidMount콜백 에서 상황에 따라 API 함수를 호출 할 수 있습니다 .
1ven

fetch()jQuery 만 사용하여 Ajax 요청을 수행하는 경우 jQuery 대신 사용할 수 있습니다 .
Fred

왜 Jquery를 사용합니까? Jquery는 거대한 라이브러리이며 불필요합니다
Robin

현재 여기에 추가하면 useEffect아마도 API 호출을 할 수 있습니다. btholt.github.io/complete-intro-to-react-v5/effects
shw

답변:


98

이 경우 내부 componentDidMount에서 ajax 호출을 수행 한 다음 업데이트 할 수 있습니다state

export default class UserList extends React.Component {
  constructor(props) {
    super(props);

    this.state = {person: []};
  }

  componentDidMount() {
    this.UserList();
  }

  UserList() {
    $.getJSON('https://randomuser.me/api/')
      .then(({ results }) => this.setState({ person: results }));
  }

  render() {
    const persons = this.state.person.map((item, i) => (
      <div>
        <h1>{ item.name.first }</h1>
        <span>{ item.cell }, { item.email }</span>
      </div>
    ));

    return (
      <div id="layout-content" className="layout-content-wrapper">
        <div className="panel-list">{ persons }</div>
      </div>
    );
  }
}

2
감사합니다. 감사합니다. "더 나은 상태 관리를위한 최고의 라이브러리"를 제안 해주세요.
Raj Rj

3
@Raj Rj 요즘 나는 그것이 Redux라고 생각합니다
Alexander T.

8
Redux는 오늘날 더 인기가 있으며 스타일은 기능 프로그래밍에서 비롯됩니다. OOP 스타일에서 온 경우 Mobx ( mobxjs.github.io/mobx )는 우수한 상태 관리 라이브러리로 업무 코드 작성에 집중하고 궁극적으로 상용구 코드를 줄일 수 있습니다.
Nhan Tran

25

플럭스 아키텍처 를 확인하고 싶을 수도 있습니다 . 또한 React-Redux Implementation을 확인하는 것이 좋습니다 . 당신의 행동에 당신의 API 호출을 넣어. 구성 요소에 모두 넣는 것보다 훨씬 깨끗합니다.

작업은 응용 프로그램 상태를 변경하거나 API 호출을 수행하기 위해 호출 할 수있는 일종의 도우미 메서드입니다.


Troper 감사합니다. API 관련 호출을 별도의 파일로 유지해야합니까? 그리고 "컴포넌트 클래스"에서 어떻게 호출합니까? 어떤 폴더 구조를 따라야합니까? 모범 사례는 무엇입니까? PS- 나는이 기본적인 질문을하기 위해 반응하는 것이 처음입니다.
Raj Rj

redux 구현에서, 액션 메소드는 컴포넌트에 주입됩니다. 이러한 메소드는 이제 호출 할 수있는 컴포넌트에 대한 소품이됩니다. 당신은 체크 아웃 할 수있다 반응-REDUX - 스타터 키트를 구조합니다.
Jei Trooper

12

fetch내부 메소드를 사용 componentDidMount하여 상태를 업데이트 하십시오 .

componentDidMount(){
  fetch('https://randomuser.me/api/')
      .then(({ results }) => this.setState({ person: results }));
}

11

이 토론은 한동안 진행되었으며 @Alexander T.의 답변은 나 같은 React의 최신 버전을 따르는 좋은 가이드를 제공했습니다. 그리고 동일한 API를 여러 번 호출하여 구성 요소를 새로 고치는 방법에 대한 추가 노하우를 공유 할 것입니다. 초보자가 처음에 직면 할 수있는 일반적인 문제 일 것입니다.

componentWillReceiveProps(nextProps)에서 공식 문서 :

prop 변경에 응답하여 상태를 업데이트해야하는 경우 (예 : 재설정) this.props 및 nextProps를 비교하고이 메소드에서 this.setState ()를 사용하여 상태 전이를 수행 할 수 있습니다.

여기서 우리는 부모 컴포넌트의 소품을 처리하고 API 호출을하고 상태를 업데이트하는 장소라고 결론 내릴 수 있습니다.

@Alexander T.의 예를 기반으로 :

export default class UserList extends React.Component {
  constructor(props) {
    super(props);
    this.state = {person: []};
  }

  componentDidMount() {
   //For our first load. 
   this.UserList(this.props.group); //maybe something like "groupOne"
  }

  componentWillReceiveProps(nextProps) {
    // Assuming parameter comes from url.
    // let group = window.location.toString().split("/")[*indexParameterLocated*];
    // this.UserList(group);

    // Assuming parameter comes from props that from parent component.
    let group = nextProps.group; // Maybe something like "groupTwo" 
    this.UserList(group);
  }

  UserList(group) {
    $.getJSON('https://randomuser.me/api/' + group)
      .then(({ results }) => this.setState({ person: results }));
  }

  render() {
    return (...)
  }
}

최신 정보

componentWillReceiveProps() 더 이상 사용되지 않습니다.

다음은 일반적인 경우 API 배포와 관련이 있다고 생각되는 수명주기 의 일부 메소드 ( Doc의 모든 메소드 )입니다. 여기에 이미지 설명을 입력하십시오

위의 다이어그램을 참조하여 :

  • 에 API 배포 componentDidMount()

    여기에서 API 호출을 수행하는 적절한 시나리오는이 컴포넌트의 컨텐츠 (API 응답에서)가 정적이며 componentDidMount()컴포넌트가 마운트되는 동안 한 번만 실행되며 심지어 새로운 소품이 상위 컴포넌트에서 전달되거나 Leading 조치가 있다는 것 re-rendering입니다.
    구성 요소는 다시 렌더링 할 수 있지만 다시 마운트 하지 않는 차이를 확인 합니다. 문서
    에서 인용 :

원격 엔드 포인트에서 데이터를로드해야하는 경우 네트워크 요청을 인스턴스화하는 것이 좋습니다.


  • 에 API 배포 static getDerivedStateFromProps(nextProps, prevState)

우리는 두 가지 종류가 있다는 것을주의해야 구성 요소 업데이트 , setState() 현재의 구성 요소없는 트리거에이 방법을지도,하지만에서 다시 렌더링하거나 새로운 소품 부모 구성 요소는 않습니다. 우리는이 방법이 장착하는 동안 발생한다는 것을 알 수있었습니다.

템플릿과 같은 현재 컴포넌트를 사용하려는 경우 API를 배치하기에 적합한 위치 이며 API의 새 매개 변수는 상위 컴포넌트에서 가져 오는 소품 입니다.
API에서 다른 응답을 받고이 state구성 요소의 내용을 변경하기 위해 여기에 새로운 내용을 반환합니다 .

예를 들어
, 상위 구성 요소에 다른 자동차에 대한 드롭 다운 목록이 있으며이 구성 요소는 선택된 자동차의 세부 사항을 표시해야합니다.


  • 에 API 배포 componentDidUpdate(prevProps, prevState)

static getDerivedStateFromProps()달리,이 메소드는 초기 렌더링을 제외한 모든 렌더링 직후에 호출됩니다. 하나의 구성 요소에서 API 호출 및 렌더링 차이를 가질 수 있습니다.

앞의 예 확장 :
우리는 2013 년 생산을 확인하려면이 차의 시리즈의 목록을 포함 할 수 있습니다 차량의 세부 정보를 표시 할 수있는 구성 요소를, 우리는 첫 번째를 이끌 ... 목록 항목을 클릭하거나 선택하거나 수 있습니다 setState()이를 반영하기 이 구성 요소에서 동작 (예 : 목록 항목 강조 표시)을 수행하고 다음에서 componentDidUpdate()새 매개 변수 (상태)로 요청을 보냅니다. 응답을 얻은 후 setState()Car 세부 사항의 다른 컨텐츠를 렌더링합니다. 다음 componentDidUpdate()으로 인해 무한 루프가 발생 하지 않도록하려면 prevState이 메서드의 시작 부분을 활용 하여 API를 전송하고 새 콘텐츠를 렌더링할지 결정 하여 상태를 비교해야 합니다.

이 방법은 정말처럼 활용 될 수있는 static getDerivedStateFromProps()소품 만의 변경 사항을 처리 할 필요 props활용하여 prevProps. 그리고 componentDidMount()초기 API 호출을 처리 하기 위해 협력해야합니다 .

문서 에서 인용 :

... 또한 현재 소품을 이전 소품과 비교하는 한 네트워크 요청을 수행하기에 좋은 곳입니다 ...


10

redux http://redux.js.org/index.html을 살펴보고 싶습니다.

그들은 API 호출을 위해 비동기 호출을 처리하는 매우 잘 정의 된 방법을 가지고 있으며 API 호출에 jQuery를 사용하는 대신 가져 오기 또는 요청 npm 패키지를 사용하고 싶습니다 . 페치 는 현재 최신 브라우저에서 지원되지만 shim도 사용할 수 있습니다 서버 측.

이 또 다른 놀라운 패키지 수퍼 에이전트 도 있습니다.이 패키지 에는 API 요청을 할 때 많은 옵션이 있으며 사용하기 매우 쉽습니다.


3

렌더 기능은 순수해야합니다. 즉, 상태와 소품 만 렌더링에 사용하고 렌더에서 상태를 수정하지 마십시오. 이는 보통 못생긴 버그를 유발하고 성능을 크게 저하시킵니다. 또한 데이터 가져 오기를 분리하고 React 앱에서 우려 사항을 렌더링하는 것이 좋습니다. 이 아이디어를 잘 설명하는이 기사를 읽는 것이 좋습니다. https://medium.com/@learnreact/container-components-c0e67432e005#.sfydn87nm


3

React v16 문서 의이 부분 은 componentDidMount ()에 대한 질문에 대답합니다.

componentDidMount ()

componentDidMount ()는 구성 요소가 마운트 된 직후에 호출됩니다. DOM 노드가 필요한 초기화는 여기로 가야합니다. 원격 엔드 포인트에서 데이터를로드해야하는 경우 네트워크 요청을 인스턴스화하는 것이 좋습니다. 이 방법은 구독을 설정하기에 좋은 장소입니다. 그렇게하면 componentWillUnmount ()에서 구독을 취소해야합니다.

보시다시피 componentDidMountAPI 호출 을 수행하고 노드에 액세스 하는 가장 좋은 장소 및 주기로 간주됩니다. 이때까지 호출 을 수행하거나보기를 업데이트하는 것이 안전합니다. jQuery를 사용하면 document.ready () 함수를 생각 나게해야합니다. 여기서 코드에서 원하는 모든 작업을 수행 할 수 있습니다.


3

1) F etch API 를 사용 하여 Endd Points에서 데이터를 가져올 수 있습니다 .

Github사용자의 모든 휴식을 가져 오는 예제

  /* Fetch GitHub Repos */
  fetchData = () => {

       //show progress bar
      this.setState({ isLoading: true });

      //fetch repos
      fetch(`https://api.github.com/users/hiteshsahu/repos`)
      .then(response => response.json())
      .then(data => {
        if (Array.isArray(data)) {
          console.log(JSON.stringify(data));
          this.setState({ repos: data ,
                         isLoading: false});
        } else {
          this.setState({ repos: [],
                          isLoading: false  
                        });
        }
      });
  };

2) 다른 대안은 Axios입니다

axios를 사용하면 http 요청 결과를 .json () 메소드로 전달하는 중간 단계를 줄일 수 있습니다. Axios는 예상 한 데이터 객체 만 반환합니다.

  import axios from "axios";

 /* Fetch GitHub Repos */
  fetchDataWithAxios = () => {

     //show progress bar
      this.setState({ isLoading: true });

      // fetch repos with axios
      axios
          .get(`https://api.github.com/users/hiteshsahu/repos`)
          .then(result => {
            console.log(result);
            this.setState({
              repos: result.data,
              isLoading: false
            });
          })
          .catch(error =>
            this.setState({
              error,
              isLoading: false
            })
          );
}

이제이 전략 중 하나를 사용하여 데이터를 가져 오도록 선택할 수 있습니다. componentDidMount

class App extends React.Component {
  state = {
    repos: [],
   isLoading: false
  };

  componentDidMount() {
    this.fetchData ();
  }

한편 데이터가로드되는 동안 진행률 표시 줄을 표시 할 수 있습니다

   {this.state.isLoading && <LinearProgress />}

2

함수 구성 요소에 후크가 있는 데이터를 가져올 수도 있습니다.

API 호출의 전체 예 : https://codesandbox.io/s/jvvkoo8pq3

두 번째 예 : https://jsfiddle.net/bradcypert/jhrt40yv/6/

const Repos = ({user}) => {
  const [repos, setRepos] = React.useState([]);

  React.useEffect(() => {
    const fetchData = async () => {
        const response = await axios.get(`https://api.github.com/users/${user}/repos`);
        setRepos(response.data);
    }

    fetchData();
  }, []);

  return (
  <div>
    {repos.map(repo =>
      <div key={repo.id}>{repo.name}</div>
    )}
  </div>
  );
}

ReactDOM.render(<Repos user="bradcypert" />, document.querySelector("#app"))

1

외부 API 호출에 대한 가장 좋은 장소 및 실습은 React Lifecycle 메소드 componentDidMount () 입니다. API 호출을 실행 한 후에는 새 render () 메소드 호출 이 트리거되도록 로컬 상태를 업데이트해야합니다 . 그러면 업데이트 된 로컬 상태가 변경됩니다. 구성 요소보기에 적용됩니다.

React에서 초기 외부 데이터 소스 호출에 대한 다른 옵션 은 클래스 의 constructor () 메소드를 가리 킵니다 . 생성자는 구성 요소 개체 인스턴스를 초기화 할 때 가장 먼저 실행되는 방법입니다. 상위 주문 구성 요소 의 문서 예제에서이 방법을 볼 수 있습니다 .

componentWillMount ()UNSAFE_componentWillMount () 메소드 는 더 이상 사용되지 않으므로 외부 API 호출에 사용해서는 안됩니다. 여기 에서이 방법이 더 이상 사용되지 않는 일반적인 이유를 확인할 수 있습니다.

어쨌든 render () 메서드 또는 render ()에서 직접 호출 된 메서드 를 외부 API 호출의 지점으로 사용 해서는 안됩니다 . 이렇게하면 응용 프로그램이 차단 됩니다.


0

깨끗한 방법은 내부 비동기 API를 호출하는 것입니다 componentDidMount시도 / 캐치 기능을 .

API를 호출하면 응답을받습니다. 그런 다음 JSON 메소드를 적용하여 응답을 JavaScript 객체로 변환합니다. 그런 다음 해당 응답 객체에서 "results"(data.results)라는 하위 객체 만 가져옵니다.

처음에는 상태에서 "userList"를 빈 배열로 정의했습니다. API를 호출하고 해당 API에서 데이터를 수신하자마자 setState 메소드를 사용하여 "results"를 userList에 지정합니다 .

render 함수 안에서 userList가 state에서 온다고 알려줍니다. userList는 객체의 배열이므로이를 통해 각 객체 "user"의 그림, 이름 및 전화 번호를 표시합니다. 이 정보를 검색하기 위해 점 표기법 (예 : user.phone)을 사용합니다.

참고 : API에 따라 응답이 다르게 보일 수 있습니다. Console.log 전체 "응답"에서 필요한 변수를 확인한 후 setState에 할당하십시오.

UserList.js

import React, { Component } from "react";

export default class UserList extends Component {
   state = {
      userList: [], // list is empty in the beginning
      error: false
   };

   componentDidMount() {
       this.getUserList(); // function call
   }

   getUserList = async () => {
       try { //try to get data
           const response = await fetch("https://randomuser.me/api/");
           if (response.ok) { // ckeck if status code is 200
               const data = await response.json();
               this.setState({ userList: data.results});
           } else { this.setState({ error: true }) }
       } catch (e) { //code will jump here if there is a network problem
   this.setState({ error: true });
  }
};

  render() {
  const { userList, error } = this.state
      return (
          <div>
            {userList.length > 0 && userList.map(user => (
              <div key={user}>
                  <img src={user.picture.medium} alt="user"/>
                  <div>
                      <div>{user.name.first}{user.name.last}</div>
                      <div>{user.phone}</div>
                      <div>{user.email}</div>
                  </div>
              </div>
            ))}
            {error && <div>Sorry, can not display the data</div>}
          </div>
      )
}}

0

취소, 인터셉터 등을 지원하는 API 요청에 axios를 사용하는 것이 좋습니다. axios와 함께 l 상태 관리에는 react-redux를 사용하고 부작용에는 redux-saga / redux-thunk를 사용하십시오.


Axios 및 redux를 사용하는 것이 데이터를 가져오고 상태를 관리하는 올바른 방법이므로 이것이 올바르지는 않지만 실제로 질문에 대답하지 않으며 주석에 더 가깝습니다.
Emile Bergeron
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.