Reaction-native: Использование async / await с setState - PullRequest
1 голос
/ 20 апреля 2019

У меня есть этот простой код.

export default class ProductDetail extends Component {

  constructor(props) {
    super(props);
    this.state = { test: null,id:this.props.navigation.state.params.productId };
    console.log(1);
  }

  componentWillMount() {
    console.log(2);
    this.getProductRequest(this.state.id);
    console.log(3);
  }

  async getProductRequest(id) {
    try {
      let api_token = await AsyncStorage.getItem('apiToken')
      let response = await fetch('...')
      let json = await response.json();
      this.setState({test: json});

    } catch(error) {
      //
    }

  }

  render() {
    console.log(4);
    console.log(this.state.test);
    return (
      <View><Text>test</Text></View>
    );
  }
}

Теперь я проверил это в отладчике:

Ожидаю такой результат:

1

2

3

4

{data: {…}, статус: "success", ...}

Но я получаю это:

1

2

3

4

1031 * пустой *

4

{data: {…}, статус: "success", ...}

Я думаю, что это означает, что render () запускается дважды!

как мне справиться с этой ошибкой?

Ответы [ 2 ]

4 голосов
/ 20 апреля 2019

Я думаю, что это означает, что render () запускается дважды!

Он делает: Один раз, прежде чем ваш асинхронный результат доступен, и затем снова, когда он есть, и вы используете setState.Это нормально и ожидаемо.

Вы не можете задержать первый рендер, ожидающий завершения асинхронной операции.Вы можете выбрать:

  1. Сделать компонент соответствующим образом, когда у него еще нет данных.Или

  2. Если вы не хотите отображать компонент на всех до завершения асинхронной операции, переместите эту операцию в родительский компонент и выполняйте только визуализацию.этот компонент, когда данные доступны, передавая данные этому компоненту как реквизиты.

1 голос
/ 20 апреля 2019

Просто чтобы добавить к ответу Т. Дж. Краудера одну вещь, которую я хотел бы сделать, это вернуть ActivityIndicator , если данные еще не получены.

import {
    View,
    Text,
    ActivityIndicator
} from 'react-native';

export default class ProductDetail extends Component {
    ... your code ...

    render() {
        if (!this.state.test) {
            return <ActivityIndicator size='large' color='black' />
        }

        console.log(4);
        console.log(this.state.test);
        return (
          <View><Text>test</Text></View>
        );
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...