React - Получение из функции внешнего API при нажатии кнопки

Я пытаюсь запустить вызов API из компонента, когда пользователь нажимает кнопку. Один параметр URL-адреса зависит от слова, которое пользователь выбрал перед нажатием кнопки. Функция выборки находится во внешней функции. Когда я вызываю функцию при нажатии кнопки и консоль регистрирую результат, он показывает undefined, вероятно, из-за асинхронного характера функции.

Как я могу решить эту проблему, если я хочу поместить ответ выборки в состояние компонента App?

import { fetchAPI } from '../fetchAPI';

export default class App extends Component {

constructor() {
    super();
    this.toggleButtonState = this.toggleButtonState.bind(this);
    state = { ... }
}

toggleButtonState() {
    let selectedWord = window.getSelection().toString();
    fetchAPI(selectedWord);
    // call the fetchAPI function and put the result into state
}

export function fetchAPI(param) {
    // param is a highlighted word from the user before it clicked the button
    fetch('https://api.com/?param=' + param)
    .then(function(result) {
        return result;
    });
 }
.then(function(result) { return result; }); - это лишнее! Это как иметь function noop(v) { return v;} ... вы бы когда-нибудь этим пользовались? ильке let x = noop(4), а не let x = 4?
Bravo 30.10.2018 23:29

Я не согласен с вами, Браво. Это делается много раз, чтобы организовать код таким образом, чтобы файлы компонентов не отправляли никаких внутренних вызовов, а выполнялись из вызываемой функции, которая импортируется из какого-либо другого модуля / файла.

Aditya 30.10.2018 23:31
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
6
2
29 281
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

toggleButtonState() {
  let selectedWord = window.getSelection().toString();
  fetchAPI(selectedWord).then(result => this.setState({result});
}

export function fetchAPI(param) {

  // param is a highlighted word from the user before it clicked the button
  return fetch('https://api.com/?param=' + param)
}

Это решит вашу проблему. Если вы не хотите изменять API выборки таким образом, просто добавьте return перед вызовом fetch, как показано ниже.

toggleButtonState() {
  let selectedWord = window.getSelection().toString();
  fetchAPI(selectedWord).then(result => this.setState({result});
}

export function fetchAPI(param) {
  return fetch('https://api.com/?param=' + param)
    .then(function(result){
      return result;
    });
}

Что происходит с твоим ответом?

Andy 30.10.2018 23:33

Функция fetchAPI возвращает обещание, и, таким образом, вызывается функция, прикрепленная к разрешению обещания, которая находится внутри метода компонента React, и состояние может быть установлено.

Aditya 30.10.2018 23:36

Попался. Обратите внимание, что я добавил ключевое слово return для вызова вызова внутри fetchAPI в экспортированной функции. В этом случае это может звучать логически одинаково, но, вероятно, на самом деле пользователь будет делать гораздо больше внутри разрешенного метода, прикрепленного к then при вызове fetch внутри fetchAPI, и поэтому я предложил просто префикс return в методе fetchAPI вместо удаления. затем заявление полностью, как сказано в первой части

Aditya 30.10.2018 23:45
Ответ принят как подходящий

Вы должны вернуть запрос fetch из вашей функции fetchAPI, и вы также хотите добавить дополнительный then и дать ему функцию, в которой вы переводите result в состояние в функции toggleButtonState.

В вашем примере then внутри функции fetchAPI является избыточным, поскольку он просто возвращает значение как есть. Вы можете удалить это и получить тот же результат.

Пример

function fetch() {
  return new Promise(resolve => setTimeout(() => resolve(42), 1000));
}

function fetchAPI(param) {
  // param is a highlighted word from the user before it clicked the button
  return fetch("https://api.com/?param = " + param);
}

class App extends React.Component {
  state = { result: null };

  toggleButtonState = () => {
    let selectedWord = window.getSelection().toString();
    fetchAPI(selectedWord).then(result => {
      this.setState({ result });
    });
  };

  render() {
    return (
      <div>
        <button onClick = {this.toggleButtonState}> Click me </button>
        <div>{this.state.result}</div>
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById("root"));
<script src = "https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src = "https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id = "root"></div>

Спасибо за ответ. Почему setTimeout и почему resolve (42)?

Doge 30.10.2018 23:48

@Doge Добро пожаловать! URL-адрес в вашем вопросе не сработал, поэтому я просто использовал это как глупый пример.

Tholle 30.10.2018 23:50

Одно из решений - предоставить обратный вызов вашей функции fetchAPI():

function fetchAPI(param, callback) {
  // param is a highlighted word from the user before it clicked the button
  return fetch("https://api.com/?param = " + param)
    .then(callback);
}

Вы можете вызвать измененную функцию следующим образом:

fetchAPI(selectedWord, result =>
  this.setState({ result });
);

Обратите внимание, что это соответствует тому же общему принципу, что и другие ответы. Вам необходимо вызвать в setState() с правильной ссылкой this. Вы можете сделать это только из функции внутри вашего класса компонента.

Другие вопросы по теме