Я пытаюсь запустить вызов 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;
});
}
Я не согласен с вами, Браво. Это делается много раз, чтобы организовать код таким образом, чтобы файлы компонентов не отправляли никаких внутренних вызовов, а выполнялись из вызываемой функции, которая импортируется из какого-либо другого модуля / файла.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


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;
});
}
Что происходит с твоим ответом?
Функция fetchAPI возвращает обещание, и, таким образом, вызывается функция, прикрепленная к разрешению обещания, которая находится внутри метода компонента React, и состояние может быть установлено.
Попался. Обратите внимание, что я добавил ключевое слово return для вызова вызова внутри fetchAPI в экспортированной функции. В этом случае это может звучать логически одинаково, но, вероятно, на самом деле пользователь будет делать гораздо больше внутри разрешенного метода, прикрепленного к then при вызове fetch внутри fetchAPI, и поэтому я предложил просто префикс return в методе fetchAPI вместо удаления. затем заявление полностью, как сказано в первой части
Вы должны вернуть запрос 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 Добро пожаловать! URL-адрес в вашем вопросе не сработал, поэтому я просто использовал это как глупый пример.
Одно из решений - предоставить обратный вызов вашей функции 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. Вы можете сделать это только из функции внутри вашего класса компонента.
.then(function(result) { return result; });- это лишнее! Это как иметьfunction noop(v) { return v;}... вы бы когда-нибудь этим пользовались? илькеlet x = noop(4), а неlet x = 4?