Async / Await для функции поиска, которая вызывает API-интерфейс в реагирующем компоненте - PullRequest
2 голосов
/ 18 апреля 2020

Я новичок в React Native и мне нужна ваша помощь.

У меня есть вызов API для функции поиска, который вызывает разные рецепты в зависимости от ввода пользователя. Я создал вызов API async / await в другом файле. Я консоль войти, и все работает нормально. Он выплевывает json в консоли. Однако я хочу реализовать этот вызов в моем SearchScreen, к которому прикреплен файл ниже.

В функции handleSearch я вызываю api, который является методом getRecipesFromApiByRecipeName(text);. text - это пользовательский ввод.

Я знаю, что каким-то образом мне нужно сделать функцию asyn c, чтобы я мог принимать вызов API и не получать

Promise {
  "_40": 0,
  "_55": null,
  "_65": 0,
  "_72": null,
}

все время. Но как ...

Я слышал, что можно выполнить вызов API в функции ComponentDidMount(), поскольку это можно сделать асин c, но API будет и должен вызываться только один раз, когда пользователь ввел свой запрос, и не после того, как Компонент был смонтирован.

Я также пытался использовать функцию .then, которая должна как-то "бесполезно" Json, но с этим не повезло.

Итак, я бы хотел, чтобы API вызывалось после того, как пользователь дал ввод, и что json можно добавить на экран. Если бы вы могли предложить, что я должен делать, или даже показать некоторые фрагменты кода. Может быть, весь мой способ атаковать это неправильно, все, что я хочу, это чтобы рецепты отображались на устройстве ... так что даже если у вас есть совершенно новая идея о том, как реализовать вызовы API, дайте мне знать, я был бы очень признателен Это.

Также дайте мне знать, если я должен что-то исправить на этом экране.

У меня также возникают трудности с пониманием того, как работает вся эта «государственная» вещь, так что если это можно объяснить как ну, это будет высоко ценится.

Заранее спасибо.

import React from 'react';
import {
  FlatList,
  Text,
  View,
  Image,
  TouchableHighlight
} from 'react-native';
import styles from './styles';
import { ListItem, SearchBar } from 'react-native-elements';
import MenuImage from '../../components/MenuImage/MenuImage';
import { getRecipesFromApiByRecipeName } from '../../data/Data';

export default class SearchScreen extends React.Component {
  static navigationOptions = ({ navigation }) => {
    const { params = {} } = navigation.state;
    return {
      headerRight: () =>
        <MenuImage
          onPress={() => {
            navigation.openDrawer();
          }}
        />
      ,
      headerTitle: () =>
        <SearchBar
          containerStyle={{
            backgroundColor: 'transparent',
            borderBottomColor: 'transparent',
            borderTopColor: 'transparent',
            width: 300

          }}
          inputContainerStyle={{
            backgroundColor: '#EDEDED',
            borderRadius: 25
          }}
          inputStyle={{
            backgroundColor: '#EDEDED',
            borderRadius: 5,
            color: 'black'
          }}
          searchIcon
          clearIcon
          onChangeText={text => params.handleSearch(text)}
          placeholder="Search"
          value={params.data}
        />
    };
  };

  constructor(props) {
    super(props);
    this.state = {
      value: '',
      data: []
    };
  }

    componentDidMount() {
    const { navigation } = this.props;
    navigation.setParams({
      handleSearch: this.handleSearch,
      data: this.getValue
    });
  }

  handleSearch = text => {
    const recipes = getRecipesFromApiByRecipeName(text); //need to get this to be able to call await.
      if (text == '') {
        this.setState({
          value: text,
          data: []
        });
      } else {
        this.setState({
          value: text,
          data: recipes
        });
      }
  };

  getValue = () => {
    return this.state.value;
  };

  onPressRecipe = item => {
    this.props.navigation.navigate('Recipe', { item });
  };

  renderRecipes = ({ item }) => (
    <TouchableHighlight underlayColor='rgba(73,182,77,0.9)' onPress={() => this.onPressRecipe(item)}>
      <View style={styles.container}>
        <Image style={styles.photo} source={{ uri: item.recipe.image }} />
        <Text style={styles.title}>{item.recipe.label}</Text>
      </View>
    </TouchableHighlight>
  );

  render() {
    return (
      <View>
        <FlatList
          vertical
          showsVerticalScrollIndicator={false}
          numColumns={2}
          data={this.state.data}
          renderItem={this.renderRecipes}
          keyExtractor={item => `${item.recipeId}`} //How does this work?
        />
      </View>
    );
  }
}

1 Ответ

1 голос
/ 18 апреля 2020

Исходя из правил синтаксиса c JavaScript, ключевое слово await может делать только то, что ему нужно, в функции async.

function a() {
  // await is not a keyword in a regular function
  var await = 5;
  console.log(await);
}

a()

async function b() {
//^^^
  // but it is a special keyword in an async function
  // by using await, we pause the code execution
  // until the promise we're awaiting one is fulfilled
  const x = await Promise.resolve(10);
  console.log(x);
}

b();

Это правило также относится к функциям стрелок:

const a = () => {
  // await is not a keyword in a regular function
  var await = 5;
  console.log(await);
}

a()

const b = async () => {
  //      ^^^^^
  // but it is a special keyword in an async function
  // by using await, we pause the code execution
  // until the promise we're awaiting one is fulfilled
  const x = await Promise.resolve(10);
  console.log(x);
}

b();

В вашем случае handleSearch - это обычная функция стрелки, поэтому await не может работать в ней. Вам нужно сделать handleSearch async функцию, которая await в рецептах:

handleSearch = async text => {
//             ^^^^^
    const recipes = await getRecipesFromApiByRecipeName(text);
//                  ^^^^^
...