簡體   English   中英

單擊按鈕時顯示來自 API 的數據。 使用 ReactJS

[英]Display data from an API when clicking a button. Using ReactJS

當我單擊信息按鈕時,我試圖顯示每個字符的數據。 我知道這是因為在onButtonClickHandler函數中它看不到狀態。 我也試過this.state.person但它給了我一個錯誤,說“無法讀取狀態”。 如果我只嘗試state.person它會給我“未定義”。

最好的方法是什么? 謝謝

API 鏈接: https : //swapi.dev/people/

import React from "react";

export default class FetchActors extends React.Component {
  state = {
    loading: true,
    person: null
  };

  async componentDidMount() {
    const url = "https://swapi.dev/api/people/";
    const response = await fetch(url);
    const data = await response.json();
    this.setState({ person: data.results, loading: false });
  }

  render() {
    if (this.state.loading) {
      return <div>loading...</div>;
    }

    if (!this.state.person.length) {
      return <div>didn't get a person</div>;
    }

   function onButtonClickHandler(state) {
      console.log(state.person);
    };


    return (
      <div>
        <h1>Actors</h1>
        {this.state.person.map(person =>(
        <div>
          <div>
            {person.name}
            <button onClick={onButtonClickHandler}>Info</button>

          </div>

        </div>
        ))}
        <button onClick={onButtonClickHandler}>Enter</button>
      </div>
    );
  }
}

如果我錯了,請糾正我

您看到這種情況的最可能原因是 javascript 內部的工作方式。 語法:

function xyz() {

}

有一個隱含的this

也許嘗試從以下位置更改您的代碼:

function onButtonClickHandler(state) {
  console.log(state.person);
};

到:

const onButtonClickHandler = () => {
  console.log(this.state.person);
};

延伸閱讀: 這里

有幾種方法可以解決您的問題; 我會給你更常見的方法。

  1. 您想將點擊處理程序定義為類(實例)方法,而不是將其聲明為渲染方法內的函數(您可以將其定義為渲染方法內的函數,但這可能不是最好的方法)超出范圍的各種原因)。
  2. 您還必須將它的“this”值綁定到類(實例),因為單擊處理程序是異步觸發的。
  3. 最后,添加一個按鈕並在點擊時觸發獲取:
class Actors extends React.Component {
  state = {
    loading: false,
    actors: undefined,
  };

  constructor(props) {
    super(props);
    this.fetchActors = this.fetchActors.bind(this);
  }

  async fetchActors() {
    this.setState({ loading: true });
    const url = "https://swapi.dev/api/people/";
    const response = await fetch(url);
    const data = await response.json();
    this.setState({ actors: data.results, loading: false });
  }

  render() {
    console.log('Actors: ', this.state.actors);
    return <button onClick={this.fetchActors}>fetch actors</button>;
  }
}

您已將函數onButtonClickHandler定義為接受一個參數並記錄該參數的person屬性的函數。 函數中的參數state與組件的state無關。 正如 javascript 所見,它們是兩個完全不相關的變量,只是碰巧具有相同的名稱。

function onButtonClickHandler(state) {
   console.log(state.person);
};

button調用onClick ,它將事件作為參數傳遞。 所以你的onButtonClickHandler正在記錄事件的person屬性,這顯然不存在。

由於您沒有使用事件中的任何信息,因此您的函數不應采用任何參數。 正如其他人所說,您還應該將此函數移到render()方法之外,以便不會在每次渲染時重新創建它。 如果您使用箭頭函數,則不需要使用bind的建議,因為它們會自動綁定。

export default class FetchActors extends React.Component {
  /*...*/

  onButtonClickHandler = () => {
     console.log(this.state.person);
  };

}

內部render()

<button onClick={this.onButtonClickHandler}>Enter</button>

您還可以將函數內聯定義為不帶參數的箭頭函數:

<button onClick={() => console.log(this.state.person)}>Enter</button>

如果您不熟悉 React,我建議您使用函數組件而不是類組件來學習。

編輯:

更新有關我們評論的答案。 我太忙於解釋做錯事的錯誤,以至於忽略了解釋如何做正確的事!

當我單擊信息按鈕時,我試圖顯示每個字符的數據。

一旦我們調用 API,我們就已經為每個角色加載了信息。 我們只需要知道我們想要顯示哪一個。 您可以添加一個expanded到您的state的屬性,並使用它來存儲當前擴展項目的索引(或idname ,無論您想要什么)。

當我們循環顯示名稱和信息按鈕時,我們檢查該字符是否是展開的字符。 如果是這樣,我們會顯示字符信息。

現在我們按鈕的onClick處理程序負責將state.expanded設置為我們單擊它的字符。

{this.state.person.map((person, i) =>(
<div>
  <div>
    {person.name}
    <button onClick={() => this.setState({expanded: i})}>Info</button>
    {this.state.expanded === i && (
      <CharacterInfo
        key={person.name}
        person={person}
      />
    )}
  </div>

代碼沙盒鏈接

有時我需要一分鍾的時間來加載更新的狀態。

import React from "react";

export default class FetchActors extends React.Component {
  state = {
    loading: true,
    person: null
  };

  async componentDidMount() {
    const url = "https://swapi.dev/api/people/";
    const response = await fetch(url);
    const data = await response.json();
    if(!data.results) { // throw error }
    this.setState({ person: data.results, loading: false }, () => {
  console.log(this.state.person) // log out your data to verify
});
  }

  render() {
    if (this.state.loading || !this.state.person) { // wait for person data
      return <div>loading...</div>;
    }else{


   function onButtonClickHandler(state) { // just make a componentDidUpdate function
      console.log(state.person);
    };


    return (
      <div>
        <h1>Actors</h1>
        {this.state.person.map(person =>(
        <div>
          <div>
            {person.name}
            <button onClick={onButtonClickHandler}>Info</button>

          </div>

        </div>
        ))}
        <button onClick={onButtonClickHandler}>Enter</button>
      </div>
    );
  }
}}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM