Nextjs не ждет начального состояния от вызова API на стороне сервера - PullRequest
0 голосов
/ 17 октября 2018

Я создал базовое приложение с NextJS, которое извлекает данные из API как на стороне сервера, так и на стороне клиента.

Для этого я создал действия и редуктор.Проблема в том, что, когда я попадаю на страницу, она приходит с сервера без состояния (я могу наблюдать это на странице-источнике), но после второй клиентской работы и получения данных.Сразу после того, как страница попадает в браузер, я вижу журнал ответов на консоли сервера.Это означает, что сервер не ожидает ответа и не может создать с ним состояние.

Я прочитал и попробовал так много решений для достижения асинхронных / ожидающих событий от stackoverflow, но ни одно из них не работает для меня, или я не смог реализовать егоправильно.

Вот файлы, которые я использую.Я думаю, что этого будет достаточно, но если вам нужна дополнительная информация, я могу поделиться другими частями.

Спасибо.

getCurrencyAction.js

import { actionTypes } from './action-types';
import fetch from 'isomorphic-unfetch'

export function fetchCurrency() {
  return dispatch => {
    dispatch(apiCurencyFetch());
    return fetch("/currency-api")
      .then(handleErrors)
      .then(res => res.json())
      .then(json => {
        dispatch(apiCurencySuccess(json));
        return json;
      })
      .catch(error => dispatch(apiCurencyError(error)));
  };
}

function handleErrors(response) {
  if (!response.ok) {
    throw Error(response.statusText);
  }
  return response;
}

export const apiCurencyFetch = () => dispatch => {
  return dispatch({
    type: actionTypes.API_CURRENCY_FETCH
  })
}

export const apiCurencySuccess = (data) => dispatch => {
  return dispatch({
    type: actionTypes.API_CURRENCY_SUCCESS,
    payload: {data}
  })
}

export const apiCurencyError = (err) => dispatch => {
  return dispatch({
    type: actionTypes.API_CURRENCY_ERROR,
    payload: {err}
  })
}

getCurrencyReducer.js

import { actionTypes } from '../actions/action-types';

const initialState = {
  loading: false,
  error: null,
  data: []
}

export default function currencies(state = initialState, action) {
  switch(action.type) {
    case actionTypes.API_CURRENCY_FETCH:
      return {
        ...state,
        loading: true,
        error: null
      };

    case actionTypes.API_CURRENCY_SUCCESS:
      return {
        ...state,
        loading: false,
        data: action.payload.data
      };

    case actionTypes.API_CURRENCY_ERROR:
      return {
        ...state,
        loading: false,
        error: action.payload.error,
      };

    default:
      return state;
  }
}

store.js

import { createStore, applyMiddleware } from 'redux'
import { composeWithDevTools } from 'redux-devtools-extension'
import thunkMiddleware from 'redux-thunk'
import reducer from './reducers'
import { actionTypes } from './actions/action-types'

export function initializeStore (initialState = {}) {
  return createStore(reducer, initialState, composeWithDevTools(applyMiddleware(thunkMiddleware)))
}

withReduxStore.js

import React from 'react'
import { initializeStore } from '../store'

const isServer = typeof window === 'undefined'
const __NEXT_REDUX_STORE__ = '__NEXT_REDUX_STORE__'

function getOrCreateStore (initialState) {
  // Always make a new store if server, otherwise state is shared between requests
  if (isServer) {
    return initializeStore(initialState)
  }

  // Create store if unavailable on the client and set it on the window object
  if (!window[__NEXT_REDUX_STORE__]) {
    window[__NEXT_REDUX_STORE__] = initializeStore(initialState)
  }
  return window[__NEXT_REDUX_STORE__]
}

export default (App) => {
  return class AppWithRedux extends React.Component {
    static async getInitialProps (appContext) {
      // Get or Create the store with `undefined` as initialState
      // This allows you to set a custom default initialState
      const reduxStore = getOrCreateStore()

      // Provide the store to getInitialProps of pages
      appContext.ctx.reduxStore = reduxStore

      let appProps = {}
      if (typeof App.getInitialProps === 'function') {
        appProps = await App.getInitialProps(appContext)
      }

      return {
        ...appProps,
        initialReduxState: reduxStore.getState()
      }
    }

    constructor (props) {
      super(props)
      this.reduxStore = getOrCreateStore(props.initialReduxState)
    }

    render () {
      return <App {...this.props} reduxStore={this.reduxStore} />
    }
  }
}

index.js

import { Component } from 'react';
import { connect } from "react-redux";

// Components
import { fetchCurrency } from '../actions'
import { Showcase, Pagebody } from '../sections/'
import Layout from '../layouts/default.js'

// Code
class Index extends Component {
  constructor (props) {
    super(props)
  }

  componentWillMount() {
    this.props.dispatch(fetchCurrency());
  }

  render() {
    return (
      <Layout>
        <Showcase />
        <Pagebody />
      </Layout>
    )
  }
}

export default connect()(Index);
...