Как обрабатывать длинные асинхронные операции в Next.js, чтобы избежать медленной загрузки страницы? - PullRequest
0 голосов
/ 07 июля 2019

При использовании next-redux-wrapper как запустить длинную асинхронную задачу, чтобы она выполнялась только на клиенте?Я не хочу использовать await на стороне сервера, поскольку это приведет к задержке начальной загрузки страницы.Я бы предпочел установить флаг загрузки при запуске задачи и показывать индикатор загрузки до ее завершения.

Допустим, моя асинхронная операция выглядит следующим образом:

function async takesLong(store) {
    store.dispatch({type: “LOADING”, payload: true});
    const result = await longOperation();  
    store.dispatch({type: “SETDATA”}, payload: data);
    return store.dispatch({type: “LOADING”, payload: false});
}

Я могу вызвать это в функции getInitialProps моей следующей страницы следующим образом:

MyPage.getInitialProps = async ({ store, isServer }) => {
  const loader = takesLong(store)
  if (isServer) await loader;   // <-- will delay client response
  return {
    someprop: "some value"
  };
};

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

  1. Запуск процесса на сервере и без использования await отображает страницу без записи результатов в хранилищепоэтому он установил в хранилище «loading» только значение «истина» и никогда не получит данные.
  2. Передача store в моем props не работает - он оказывается пустым объектом ({ }) в клиенте.
  3. Попытка запустить его внутри моего компонента, похоже, не работает по нескольким причинам:

    a) У меня нет store объект, доступный в компоненте React (только в getInitialProps, который не вызывается на клиенте).

    b) Даже если я использую действия вместо store.dispatch в компоненте, когда я могу вызватьэто безопасно?Я не могу сделать это во время render, так как это изменит состояние Redux, и componentWillReceiveProps не будет вызвано до того, как первая клиентская сторона render

Естьчетко определенный шаблон для отсрочки длинной операции на стороне клиента при использовании Next?

Ответы [ 2 ]

1 голос
/ 15 июля 2019

Использование связанных действий во время componentDidMount работ. Спасибо @eenagy за предложение. Делать вещи в таком порядке, кажется, делает то, что нужно:

import { bindActionCreators } from "redux";
import { setLoading, setError, setData } from "../actions";

componentDidMount() {
  if (!this.props.haveData && !this.props.loading && !this.props.error) {
    this.props.setLoading(true);
    loadSomeData()        // <-- this takes a while to complete
      .then( data => {
        this.props.setData(data);
        this.props.setLoading(false);
      })
      .catch( err => {
        this.props.setError(err);
        this.props.setLoading(false);
      });
  }
}

render() {
  if (this.props.loading) return (<Loading/>);
  return (/*regular page*/);
}

export const mapDispatchToProps = dispatch => {
  return bindActionCreators({ setLoading, setError, setData }, dispatch);
};

export default connect(mapStateToProps, mapDispatchToProps)(Component);

Таким образом, если исходные данные еще не загружены (скажем, на другой странице), они будут сброшены, когда компонент монтируется и работает асинхронно до завершения операции и вызывает действия в redux для повторного рендеринга страницы.

1 голос
/ 15 июля 2019

Выполните длинную асинхронную задачу на componentDidMount, она будет выполняться только на стороне клиента. Реакция в SSR не запускается componentDidMount ловушка жизненного цикла.

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