react js'de API çağrısı yapmanın doğru yolu nedir?


137

Yakın zamanda Angular'dan ReactJs'e geçtim. API çağrıları için jQuery kullanıyorum. Bir listede yazdırılacak rastgele bir kullanıcı listesi döndüren bir API'm var.

API çağrılarımı nasıl yazacağımdan emin değilim. Bunun için en iyi uygulama nedir?

Aşağıdakini denedim ama herhangi bir çıktı alamıyorum. Gerekirse alternatif API kitaplıkları uygulamaya açığım.

Kodum aşağıdadır:

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
Hangi devlet yönetim kütüphanesini kullandığınıza bağlıyım. Hiç kullanmıyorsanız, api çağrılarınızı ayrı bir dosyaya taşıyabilir ve geri aramada sizin durumunuzdaki api işlevlerini çağırabilirsiniz componentDidMount.
1ven

fetch()Ajax isteklerini yapmak için yalnızca jQuery kullanıyorsanız , jQuery yerine kullanabilirsiniz.
Fred

Neden Jquery kullanıyorsunuz? Jquery büyük bir kitaplık ve gereksiz
Robin

Sadece buraya ekleyerek, şu anda useEffectmuhtemelen api çağrılarının yapılacağı yer. Bkz btholt.github.io/complete-intro-to-react-v5/effects
shw

Yanıtlar:


98

Bu durumda, içeriden ajax araması yapabilir componentDidMountve ardından güncelleme yapabilirsiniz.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
İşe yaradı, teşekkürler .. Lütfen bana "daha iyi devlet yönetimi için en iyi kitaplığın hangisi olduğunu" önerebilir misiniz?
Raj Rj

3
@Raj Rj bu günlerde Redux olduğunu düşünüyorum
Alexander T.

8
Redux bu günlerde daha popüler, stili işlevsel programlamadan geliyor. OOP stilinden geliyorsanız, Mobx ( mobxjs.github.io/mobx ) mükemmel bir durum yönetimi kitaplığıdır, iş kodu yazmaya odaklanmanızı sağlar ve sonuçta klişe kodunuzu azaltır
Nhan Tran

25

Flux Mimarisine göz atmak isteyebilirsiniz . React-Redux Uygulamasına da bakmanızı tavsiye ederim . API çağrılarınızı eylemlerinize ekleyin. Hepsini bileşenin içine koymaktan çok daha temiz.

Eylemler, uygulama durumunuzu değiştirmek veya api çağrıları yapmak için arayabileceğiniz bir tür yardımcı yöntemlerdir.


Troper Teşekkür ederim. Öyleyse, API ile ilgili çağrılarımı ayrı dosyalarda tutmalı mıyım? Ve onları "bileşen sınıfımda" nasıl çağırırım? hangi klasör yapısını izlemeliyim? en iyi uygulama nedir? Not: Tepki verme konusunda yeniyim, bu yüzden bu temel soruları soruyorum.
Raj Rj

Redux uygulamasında, bileşenlere eylem yöntemleri enjekte edilir. Bu yöntemler şimdi çağırabileceğiniz bileşeninize destek olacaktır. Dışarı kontrol edebilirsiniz tepki-redux-marş-kit yapısı için.
Jei Trooper

12

Durumu güncellemek için fetchiçindeki yöntemi kullanın componentDidMount:

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

11

Bu tartışma bir süredir devam ediyor ve @Alexander T.'nin cevabı, benim gibi daha yeni React için izlenecek iyi bir rehber oldu. Ve bileşeni yenilemek için aynı API'yi birden çok kez çağırmakla ilgili bazı ek bilgiler paylaşacağım, bunun muhtemelen başlangıçta yeni başlayanların karşılaşabileceği yaygın bir sorun olduğunu düşünüyorum.

componentWillReceiveProps(nextProps), resmi belgelerden :

Özellik değişikliklerine yanıt olarak durumu güncellemeniz gerekirse (örneğin, sıfırlamak için), this.props ve nextProps'ı karşılaştırabilir ve bu yöntemde this.setState () kullanarak durum geçişleri gerçekleştirebilirsiniz.

Ana bileşenden props işlediğimiz, API çağrılarına sahip olduğumuz ve güncelleme durumunun burası olduğu sonucuna varabiliriz.

@Alexander T.'nin örneğine dayanarak:

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

Güncelleme

componentWillReceiveProps() kullanımdan kaldırılacaktır.

Genel durumda API dağıtımı ile ilgili olacağını düşündüğüm yaşam döngüsündeki yalnızca bazı yöntemler (tümü Doc'ta ): görüntü açıklamasını buraya girin

Yukarıdaki diyagrama başvurarak:

  • API'yi şurada dağıtın: componentDidMount()

    Burada API çağrısına sahip olmak için uygun senaryo, bu bileşenin içeriğinin (API'nin yanıtından) statik olacağı componentDidMount(), bileşen monte edilirken yalnızca bir kez tetikleneceği , hatta yeni proplar bile üst bileşenden geçilecek veya önderlik edilecek eylemlere sahip olacağıdır re-rendering.
    Bileşen, yeniden oluşturmak için farkı kontrol eder ancak yeniden monte etmez . Dokümandan
    alıntı :

Uzak bir uç noktadan veri yüklemeniz gerekiyorsa, burası ağ talebini somutlaştırmak için iyi bir yerdir.


  • API'yi şurada dağıtın: static getDerivedStateFromProps(nextProps, prevState)

Biz iki çeşit olduğunu fark etmelidir bileşen güncellenmesi , setState() şimdiki bileşeninde olur değil tetikleyici için bu yöntemi yönlendirmiyor, ancak gelen yeniden oluşturma ya da yeni sahne ebeveyn bileşeni yok. Bu yöntemin montaj sırasında da ateşlendiğini öğrendik.

Mevcut bileşeni bir şablon gibi kullanmak istiyorsak ve API için yeni parametreler üst bileşenden gelen props ise, API'yi dağıtmak için uygun bir yerdir .
API'den farklı bir yanıt alıyoruz ve statebu bileşenin içeriğini değiştirmek için burada yeni bir yanıt gönderiyoruz .

Örneğin:
Üst bileşendeki farklı Arabalar için bir açılır listemiz var, bu bileşenin seçilenin ayrıntılarını göstermesi gerekiyor.


  • API'yi şurada dağıtın: componentDidUpdate(prevProps, prevState)

Farklı static getDerivedStateFromProps() , bu yöntem ilk işleme hariç her işlemeden hemen sonra çağrılır. API çağrısı yapabilir ve tek bir bileşende fark oluşturabilirdik.

Önceki örneği genişletin:
Otomobilin ayrıntılarını gösterecek bileşen, bu otomobilin bir dizi listesini içerebilir, 2013 üretimini kontrol etmek istersek, setState()bunu yansıtan bir ilke yönlendirmek için liste öğesini tıklayabilir veya seçebilir veya ... Bu bileşendeki davranış (liste öğesini vurgulamak gibi) ve aşağıda componentDidUpdate()talebimizi yeni parametrelerle (durum) gönderiyoruz. Yanıtı aldıktan sonra, setState()yine Araba detaylarının farklı içeriğini oluşturuyoruz. Aşağıdakilerin componentDidUpdate()sonsuz döngüye neden olmasını önlemek için prevState, API'yi gönderip yeni içeriği oluşturup oluşturmayacağımıza karar vermek için bu yöntemin başında kullanarak durumu karşılaştırmamız gerekir .

Bu yöntem gerçekten static getDerivedStateFromProps()sahne donanımlarında olduğu gibi kullanılabilir , ancak değişikliklerini propskullanarak halletmek gerekir prevProps. Ve componentDidMount()ilk API çağrısını idare etmek için işbirliği yapmamız gerekiyor .

Dokümandan alıntı :

... Mevcut donanımı önceki donanımlarla karşılaştırdığınız sürece burası ağ istekleri yapmak için de iyi bir yerdir ...


10

Redux http://redux.js.org/index.html adresine bir göz atmanızı istiyorum.

Zaman uyumsuz çağrıları, yani API çağrılarını işlemek için çok iyi tanımlanmış bir yolu var ve API çağrıları için jQuery kullanmak yerine, getirme veya istek npm paketlerini kullanmanızı tavsiye ederim , getirme şu anda modern tarayıcılar tarafından desteklenmektedir, ancak şim de mevcuttur. sunucu tarafı.

Ayrıca, API talebinde bulunurken birçok seçeneğe sahip olan ve kullanımı çok kolay olan başka bir şaşırtıcı süper ajan daha var.


3

Oluşturma işlevi saf olmalıdır, bu sadece render için state ve props kullandığı anlamına gelir, asla render sırasında durumu değiştirmeye çalışmayın, bu genellikle çirkin hatalara neden olur ve performansı önemli ölçüde düşürür. React Uygulamanızda veri getirmeyi ayırırsanız ve endişeleri ortaya koyarsanız da iyi bir nokta. Bu fikri çok iyi anlatan bu makaleyi okumanızı tavsiye ederim. https://medium.com/@learnreact/container-components-c0e67432e005#.sfydn87nm


3

React v16 belgelerinin bu bölümü sorunuzu yanıtlayacaktır, componentDidMount () hakkında okuyun:

componentDidMount ()

componentDidMount (), bir bileşen bağlandıktan hemen sonra çağrılır. DOM düğümlerini gerektiren başlatma buraya gitmelidir. Uzak bir uç noktadan veri yüklemeniz gerekiyorsa, burası ağ talebini somutlaştırmak için iyi bir yerdir. Bu yöntem, herhangi bir abonelik oluşturmak için iyi bir yerdir. Bunu yaparsanız, componentWillUnmount () 'da aboneliğinizi iptal etmeyi unutmayın.

Gördüğünüz gibi, componentDidMount , api çağrısını yapmak , ayrıca düğüme erişmek için en iyi yer ve döngü olarak kabul edilir; bu, aramayı yapmak, görünümü güncellemek veya eğer hazırsanız, belge hazır olduğunda yapabileceğiniz her şeyi güvenli olduğu anlamına gelir. jQuery kullanarak, bir şekilde size document.ready () işlevini hatırlatmalıdır; burada kodunuzda yapmak istediğiniz her şeye hazır olduğundan emin olabilirsiniz ...


3

1) Endd Points'ten veri almak için F etch API'sini kullanabilirsiniz :

GithubBir kullanıcı için tüm depoyu getirme örneği

  /* 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) Diğer Alternatif Axios'tur

Aksiyoları kullanarak http isteğinin sonuçlarını .json () yöntemine geçirmenin orta adımını kesebilirsiniz. Axios, beklediğiniz veri nesnesini döndürür.

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

Şimdi, bu stratejilerden herhangi birini kullanarak verileri getirmeyi seçebilirsiniz. componentDidMount

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

  componentDidMount() {
    this.fetchData ();
  }

Bu arada, veriler yüklenirken ilerleme çubuğunu gösterebilirsiniz

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

2

Verileri kancalarla da getirebilirsinizİşlev bileşenlerinizdeki .

api çağrısı ile tam örnek: https://codesandbox.io/s/jvvkoo8pq3

ikinci örnek: 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

Harici API çağrıları için en iyi yer ve uygulama React Lifecycle yöntemi componentDidMount () ' dur ; burada API çağrısının yürütülmesinden sonra, new render () tetiklenecek yerel durumu güncellemeniz gerekir. yöntem çağrısının , ardından güncellenmiş yerel durumdaki değişiklikler bileşen görünümüne uygulanabilir.

React'teki ilk harici veri kaynağı çağrısı için diğer seçenek , sınıfın constructor () yöntemini işaret eder . Yapıcı, bileşen nesne örneğinin başlatılmasında yürütülen ilk yöntemdir. Bu yaklaşımı, Yüksek Sıralı Bileşenler için belge örneklerinde görebilirsiniz .

ComponentWillMount () ve UNSAFE_componentWillMount () yöntemi , kullanımdan kaldırılması amaçlandığından harici API çağrıları için kullanılmamalıdır. Burada yaygın nedenleri, bu yöntemin neden kullanımdan kaldırılacağını görebilirsiniz.

Her neyse, render () yöntemini veya doğrudan render () 'dan harici API çağrısı noktası olarak çağrılan yöntemi asla kullanmamalısınız . Bunu yaparsanız başvurunuz engellenecektir .


0

Temiz bir yol, try / catch işlevi ile componentDidMount içinde zaman uyumsuz bir API çağrısı yapmaktır .

Bir API'yi çağırdığımızda bir yanıt alıyoruz. Ardından yanıtı JavaScript nesnesine dönüştürmek için üzerine JSON yöntemini uyguluyoruz. Daha sonra bu yanıt nesnesinden yalnızca "results" adlı alt nesnesini (data.results) alıyoruz.

Başlangıçta "userList" in state'i boş bir dizi olarak tanımladık. API çağrısı yapar ve bu API'den veri alır almaz, setState yöntemini kullanarak "sonuçları" userList'e atarız .

Render fonksiyonunun içinde userList'in state'den geleceğini söylüyoruz. UserList, bir resim, bir isim ve her bir nesnenin "kullanıcı" nın bir telefon numarasını görüntülemek için bununla eşleştirdiğimiz nesneler dizisi olduğundan. Bu bilgileri geri almak için nokta notasyonu kullanıyoruz (örn. User.phone).

NOT : API'nize bağlı olarak yanıtınız farklı görünebilir. Console.log'da hangi değişkenlere ihtiyacınız olduğunu görmek için tüm "yanıtı" yazın ve ardından bunları setState'te atayın.

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

İptali, engelleyicileri vb. Destekleyen api isteği için axios kullanmak harika olurdu. Aksiyoların yanı sıra, durum yönetimi için react-redux ve yan etkiler için redux-saga / redux-thunk kullanıyorum.


Bu yanlış olmasa da, axios ve redux kullanmak verileri almak ve durumu yönetmek için geçerli bir yol olduğundan, soruyu gerçekten yanıtlamaz ve bir yoruma daha yakındır.
Emile Bergeron
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.