apa cara yang benar untuk melakukan panggilan API dalam bereaksi js?

137

Saya baru saja pindah dari Angular ke ReactJs. Saya menggunakan jQuery untuk panggilan API. Saya memiliki API yang mengembalikan daftar pengguna acak yang akan dicetak dalam daftar.

Saya tidak yakin bagaimana cara menulis panggilan API saya. Apa praktik terbaik untuk ini?

Saya mencoba yang berikut tetapi saya tidak mendapatkan hasil apa pun. Saya terbuka untuk mengimplementasikan pustaka API alternatif jika perlu.

Di bawah ini adalah kode saya:

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>
    )
  }
}
Raj Rj
sumber
2
Saya tergantung pada perpustakaan manajemen negara apa yang Anda gunakan. Jika Anda tidak menggunakan apapun, Anda dapat memindahkan panggilan api ke file yang terpisah, dan memanggil fungsi api dalam situasi Anda dalam componentDidMountpanggilan balik.
1ven
Anda bisa menggunakan fetch()alih-alih jQuery jika Anda hanya menggunakan jQuery untuk melakukan permintaan Ajax.
Fred
Mengapa menggunakan Jquery? Jquery adalah perpustakaan yang sangat besar dan tidak perlu
Robin
Hanya menambahkan di sini bahwa saat useEffectini mungkin merupakan tempat untuk melakukan panggilan api sekarang. Lihat btholt.github.io/complete-intro-to-react-v5/effects
shw

Jawaban:

98

Dalam hal ini, Anda dapat melakukan panggilan ajax di dalam componentDidMount, dan kemudian memperbaruistate

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>
    );
  }
}
Alexander T.
sumber
2
Itu berhasil, terima kasih .. Bisakah Anda menyarankan saya "perpustakaan mana yang terbaik untuk manajemen negara yang lebih baik"
Raj Rj
3
@ Raj Rj pada hari-hari ini saya pikir itu adalah Redux
Alexander T.
8
Redux lebih populer saat ini, gayanya berasal dari pemrograman fungsional. Jika Anda berasal dari gaya OOP, Mobx ( mobxjs.github.io/mobx ) adalah pustaka manajemen negara yang sangat baik, memungkinkan Anda fokus pada penulisan kode bisnis dan pada akhirnya mengurangi kode boilerplate Anda
Nhan Tran
25

Anda mungkin ingin melihat Arsitektur Flux . Saya juga merekomendasikan memeriksa Implementasi React-Redux . Masukkan panggilan api Anda dalam tindakan Anda. Ini jauh lebih bersih daripada memasukkan semuanya ke dalam komponen.

Tindakan adalah semacam metode pembantu yang dapat Anda panggil untuk mengubah status aplikasi Anda atau melakukan panggilan api.

Jei Trooper
sumber
Troper, terima kasih. Jadi, haruskah saya menjaga panggilan terkait API saya di file terpisah? Dan bagaimana cara memanggil mereka di "kelas komponen" saya? struktur folder apa yang harus saya ikuti? apa praktik terbaik? PS- Saya baru bereaksi sehingga mengajukan pertanyaan mendasar ini.
Raj Rj
Dalam implementasi redux, metode aksi disuntikkan ke komponen. Metode ini sekarang akan menjadi alat peraga untuk komponen Anda yang dapat Anda panggil. Anda dapat memeriksa react-redux-starter-kit untuk struktur.
Jei Trooper
12

Gunakan fetchmetode di dalam componentDidMountuntuk memperbarui status:

componentDidMount(){
  fetch('https://randomuser.me/api/')
      .then(({ results }) => this.setState({ person: results }));
}
love-for-coding
sumber
11

Diskusi ini telah berlangsung beberapa lama dan jawaban @Alexander T. memberikan panduan yang baik untuk mengikuti React seperti saya. Dan saya akan berbagi beberapa pengetahuan tambahan tentang memanggil API yang sama beberapa kali untuk menyegarkan komponen, saya pikir itu mungkin masalah umum yang mungkin dihadapi pemula pada awalnya.

componentWillReceiveProps(nextProps), dari dokumentasi resmi :

Jika Anda perlu memperbarui status sebagai respons terhadap perubahan prop (misalnya, untuk mengatur ulang), Anda dapat membandingkan this.props dan nextProps dan melakukan transisi status menggunakan this.setState () dalam metode ini.

Kita dapat menyimpulkan bahwa di sini adalah tempat kami menangani alat peraga dari komponen induk, memiliki panggilan API, dan memperbarui status.

Berdasarkan contoh @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 (...)
  }
}

Memperbarui

componentWillReceiveProps() akan ditinggalkan.

Berikut ini hanya beberapa metode (semuanya dalam Doc ) dalam siklus hidup yang saya pikir akan terkait dengan penerapan API dalam kasus umum: masukkan deskripsi gambar di sini

Dengan merujuk diagram di atas:

  • Sebarkan API di componentDidMount()

    Skenario yang tepat untuk melakukan panggilan API di sini adalah bahwa konten (dari respons API) komponen ini akan statis, componentDidMount()hanya menyala sekali saat komponen sedang dipasang, bahkan alat peraga baru dilewatkan dari komponen induk atau memiliki tindakan untuk memimpin re-rendering.
    Komponen memeriksa perbedaan untuk merender ulang tetapi tidak memasang kembali .
    Kutipan dari doc :

Jika Anda perlu memuat data dari titik akhir jarak jauh, ini adalah tempat yang baik untuk membuat instantiate permintaan jaringan.


  • Sebarkan API di static getDerivedStateFromProps(nextProps, prevState)

Kita harus memperhatikan bahwa ada dua jenis pembaruan komponen , setState() dalam komponen saat ini tidak akan memicu metode ini, tetapi rendering ulang atau alat peraga baru dari komponen induk lakukan. Kami dapat menemukan bahwa metode ini juga menyala saat pemasangan.

Ini adalah tempat yang tepat untuk menggunakan API jika kami ingin menggunakan komponen saat ini seperti templat, dan parameter baru untuk API adalah alat peraga yang berasal dari komponen induk .
Kami menerima respons berbeda dari API dan mengembalikan yang baru di statesini untuk mengubah konten komponen ini.

Sebagai contoh:
Kami memiliki daftar dropdown untuk Mobil yang berbeda di komponen induk, komponen ini perlu menunjukkan detail dari yang dipilih.


  • Sebarkan API di componentDidUpdate(prevProps, prevState)

Berbeda dari static getDerivedStateFromProps(), metode ini dipanggil segera setelah setiap rendering kecuali rendering awal. Kami dapat membuat panggilan API dan membuat perbedaan dalam satu komponen.

Perluas contoh sebelumnya:
Komponen untuk menampilkan detail Mobil mungkin berisi daftar seri mobil ini, jika kita ingin memeriksa yang produksi 2013, kita dapat mengklik atau memilih atau ... daftar item untuk memimpin yang pertama setState()untuk mencerminkan ini perilaku (seperti menyoroti item daftar) di komponen ini, dan berikut ini componentDidUpdate()kami mengirim permintaan kami dengan parameter baru (status). Setelah mendapatkan respons, kami setState()kembali untuk merender konten yang berbeda dari detail Mobil. Untuk mencegah hal-hal berikut componentDidUpdate()dari menyebabkan infinity loop, kita perlu membandingkan keadaan dengan memanfaatkan prevStatedi awal metode ini untuk memutuskan apakah kita mengirim API dan merender konten baru.

Metode ini benar-benar dapat dimanfaatkan seperti halnya static getDerivedStateFromProps()dengan alat peraga, tetapi perlu menangani perubahan propsdengan memanfaatkan prevProps. Dan kita perlu bekerja sama dengan componentDidMount()untuk menangani panggilan API awal.

Kutipan dari doc :

... Ini juga tempat yang baik untuk melakukan permintaan jaringan selama Anda membandingkan alat peraga saat ini dengan alat peraga sebelumnya ...

Carr
sumber
10

Saya ingin Anda melihat redux http://redux.js.org/index.html

Mereka memiliki cara yang sangat baik dalam menangani panggilan async yaitu panggilan API, dan alih-alih menggunakan jQuery untuk panggilan API, saya ingin merekomendasikan menggunakan fetch atau meminta paket npm, fetch saat ini didukung oleh browser modern, tetapi shim juga tersedia untuk sisi server.

Ada juga ini paket superagent yang luar biasa , yang memiliki banyak pilihan ketika membuat permintaan API dan sangat mudah digunakan.

Devarsh Shah
sumber
3

Fungsi render harus murni, artinya hanya menggunakan status dan alat peraga untuk membuat, jangan pernah mencoba mengubah keadaan dalam render, ini biasanya menyebabkan bug jelek dan menurunkan kinerja secara signifikan. Ini juga merupakan poin yang baik jika Anda memisahkan pengambilan data dan membuat masalah di Aplikasi Bereaksi Anda. Saya sarankan Anda membaca artikel ini yang menjelaskan ide ini dengan sangat baik. https://medium.com/@learnreact/container-components-c0e67432e005#.sfydn87nm

Nhan Tran
sumber
3

Bagian dari dokumentasi React v16 ini akan menjawab pertanyaan Anda, baca tentang componentDidMount ():

componentDidMount ()

componentDidMount () dipanggil segera setelah komponen di-mount. Inisialisasi yang memerlukan node DOM harus pergi di sini. Jika Anda perlu memuat data dari titik akhir jarak jauh, ini adalah tempat yang baik untuk membuat instantiate permintaan jaringan. Metode ini adalah tempat yang baik untuk mengatur langganan apa pun. Jika Anda melakukannya, jangan lupa berhenti berlangganan di componentWillUnmount ().

Seperti yang Anda lihat, componentDidMount dianggap sebagai tempat dan siklus terbaik untuk melakukan panggilan api , juga mengakses node, berarti saat ini aman untuk melakukan panggilan, memperbarui tampilan atau apa pun yang dapat Anda lakukan ketika dokumen siap, jika Anda siap menggunakan jQuery, ini seharusnya mengingatkan Anda pada document.ready () fungsi, di mana Anda dapat memastikan semuanya siap untuk apa pun yang ingin Anda lakukan dalam kode Anda ...

Alireza
sumber
3

1) Anda dapat menggunakan F etch API untuk mengambil data dari Endd Points:

Contoh mengambil semua Githubistirahat untuk pengguna

  /* 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) Alternatif Lainnya adalah Aksioma

Menggunakan aksioma Anda dapat memotong langkah tengah melewati hasil permintaan http ke metode .json (). Axios baru saja mengembalikan objek data yang Anda harapkan.

  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
            })
          );
}

Sekarang Anda dapat memilih untuk mengambil data menggunakan salah satu strategi ini di componentDidMount

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

  componentDidMount() {
    this.fetchData ();
  }

Sementara itu Anda dapat menampilkan bilah kemajuan saat data dimuat

   {this.state.isLoading && <LinearProgress />}
Hitesh Sahu
sumber
2

Anda juga dapat mengambil data dengan kait di komponen fungsi Anda

contoh lengkap dengan panggilan api: https://codesandbox.io/s/jvvkoo8pq3

contoh kedua: 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"))
iamnotsam
sumber
1

Karena tempat dan praktik terbaik untuk panggilan API eksternal adalah React Lifecycle method componentDidMount () , di mana setelah eksekusi panggilan API Anda harus memperbarui status lokal yang akan dipicu panggilan metode render () baru , maka perubahan di negara bagian yang diperbarui akan diterapkan pada tampilan komponen.

Sebagai pilihan lain untuk panggilan sumber data eksternal awal di Bereaksi adalah menunjuk konstruktor () metode kelas. Konstruktor adalah metode pertama yang dijalankan pada inisialisasi instance objek komponen. Anda bisa melihat pendekatan ini dalam contoh dokumentasi untuk Komponen Orde Tinggi .

Method methodWillMount () dan UNSAFE_componentWillMount () tidak boleh digunakan untuk panggilan API eksternal, karena mereka dimaksudkan untuk tidak digunakan lagi. Di sini Anda bisa melihat alasan umum, mengapa metode ini akan usang.

Lagi pula Anda tidak boleh menggunakan metode render () atau metode yang dipanggil langsung dari render () sebagai titik untuk panggilan API eksternal. Jika Anda melakukan ini, aplikasi Anda akan diblokir .

zdrsoft
sumber
0

Cara bersih adalah membuat panggilan API asinkron di dalam componentDidMount dengan fungsi coba / tangkap .

Ketika kami memanggil API, kami menerima respons. Kemudian kami menerapkan metode JSON di atasnya, untuk mengubah respons menjadi objek JavaScript. Kemudian kita ambil dari objek respons itu hanya objek anaknya yang bernama "hasil" (data.result).

Pada awalnya kami mendefinisikan "userList" dalam keadaan sebagai array kosong. Segera setelah kami melakukan panggilan API dan menerima data dari API itu, kami menetapkan "hasil" ke userList menggunakan metode setState .

Di dalam fungsi render, kami memberi tahu bahwa userList akan berasal dari negara. Karena userList adalah larik objek yang kami petakan, untuk menampilkan gambar, nama, dan nomor telepon dari masing-masing objek "pengguna". Untuk mengambil informasi ini, kami menggunakan notasi titik (mis., Pengguna ponsel).

CATATAN : tergantung pada API Anda, respons Anda mungkin terlihat berbeda. Console.log seluruh "respons" untuk melihat variabel mana yang Anda butuhkan darinya, dan kemudian tetapkan di 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>
      )
}}
Tania Shulga
sumber
0

Akan bagus untuk menggunakan aksioma untuk permintaan api yang mendukung pembatalan, pencegat dll. Bersama dengan aksioma, saya menggunakan reaksi-redux untuk manajemen negara dan redux-saga / redux-thunk untuk efek samping.

Shivang Gupta
sumber
Meskipun ini tidak salah, karena menggunakan aksioma dan reduks adalah cara yang valid untuk mengambil data dan mengelola keadaan, itu tidak benar-benar menjawab pertanyaan dan lebih dekat ke komentar.
Emile Bergeron