Сделка со случайно отсроченными обещаниями в React - PullRequest
0 голосов
/ 15 января 2019

Иногда при оценке проектов React я сталкиваюсь с чем-то вроде этого:

export default () => new Promise((resolve, reject) => {
  setTimeout(() => (Math.round(Math.random()) === 0 ? resolve(countries) : reject()), 100);
});

Для имитации API, который может иметь или не иметь задержку.

Мой вопрос: когдаЯ хочу получить это обещание в компоненте React, в частности в ComponentDidMount(), что мне нужно сделать, чтобы render() ожидал, что это обещание отобразит все, что мне нужно?Какая лучшая практика вокруг этого?

Спасибо!

Ответы [ 4 ]

0 голосов
/ 15 января 2019

Это не относится к обещанию, которое использует случайную задержку или обещания вообще. Нулевая задержка setTimeout или обещание с мгновенным разрешением приведет к тому же результату, хотя и будет едва заметным. Выполнение render не может быть отложено.

Первоначальный рендеринг будет выполняться любым способом. Если состояние компонента изменяется асинхронно, render должен правильно обрабатывать исходное состояние:

state = { data: null };

componentDidMount() {
  Promise.resolve('foo').then(data => this.setState({ data }));
}

render() {
  return this.state.data ? (
    <div>{this.state.data}</div>
  ) : (
    'No data'
  );
}
0 голосов
/ 15 января 2019

Вы можете иметь состояние isLoading в своем компоненте, которое вы установили на false, когда обещание выполнено, и использовать его для визуализации null до тех пор.

Пример

const countries = ["gb", "se"];
const getCountries = () =>
  new Promise((resolve, reject) => {
    setTimeout(
      () => (Math.round(Math.random()) === 0 ? resolve(countries) : reject()),
      2000
    );
  });

class App extends React.Component {
  state = { isLoading: true, error: "", countries: [] };

  componentDidMount() {
    getCountries()
      .then(countries => {
        this.setState({ isLoading: false, countries });
      })
      .catch(() => {
        this.setState({ isLoading: false, error: "Fetching countries failed" });
      });
  }

  render() {
    const { isLoading, error, countries } = this.state;

    if (isLoading) {
      return null;
    }
    if (error) {
      return <div>{error}</div>;
    }

    return (
      <div>
        {countries.map(country => (
          <div key={country}>{country}</div>
        ))}
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
0 голосов
/ 15 января 2019

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

Минимальный код будет выглядеть следующим образом:

class MyComponent extends React.Component {
    constructor(props) {
        super(props)

        this.state = {
            show: false
        }
    }

    componentDidMount = async () => {
        try {
            await new Promise((resolve, reject) => {
                setTimeout(() => (Math.round(Math.random()) === 0 ? resolve(countries) : reject()), 100);
            });
            this.setState({ show: true })
        } catch(err){

        }
    }

    render = () => this.state.show ? <div>My content</div> : <div/>
}

Очевидно, что вы можете заменить созданное Обещание на экспортируемую вами переменную и заменить преобразованный компонент на любой другой.

0 голосов
/ 15 января 2019

Вам не нужно ничего делать. Компонент все еще должен иметь возможность визуализации во время ожидания, например, некоторое состояние, которое будет заполнено результатом симулированного вызова API. Когда обещание разрешается, если оно устанавливает какое-либо состояние для компонента, компонент будет повторно визуализирован с новыми данными.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...