Skip to content

Commit

Permalink
Make SSR wait for card data
Browse files Browse the repository at this point in the history
  • Loading branch information
Saluev committed Mar 9, 2019
1 parent 8b1f995 commit f295955
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 7 deletions.
13 changes: 10 additions & 3 deletions frontend/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,17 @@ app.get("*", (req, res) => {
const initialState = {
page: {
type: "home"
}
},
promises: []
};
const {content, preloadedState} = render(initialState, {pathname: req.url});
res.send(template("Habr demo app", preloadedState, content));
render(initialState, {pathname: req.url}).then(result => {
const {content, preloadedState} = result;
const response = template("Habr demo app", preloadedState, content);
res.send(response);
}, (reason) => {
console.log(reason);
res.status(500).send("Server side rendering failed!");
});
});

app.listen(process.env.APP_FRONTEND_PORT);
24 changes: 22 additions & 2 deletions frontend/src/redux/actions.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import {isServerSide} from "../utility";
import fetch from "cross-fetch";

export const ADD_PROMISE = "ADD_PROMISE";
export const REMOVE_PROMISE = "REMOVE_PROMISE";
export const START_FETCHING_CARD = "START_FETCHING_CARD";
export const FINISH_FETCHING_CARD = "FINISH_FETCHING_CARD";
export const NAVIGATE = "NAVIGATE";
Expand All @@ -12,6 +14,20 @@ function apiPath() {
return "http://localhost:40001/api/v1";
}

function addPromise(promise) {
return {
type: ADD_PROMISE,
promise: promise
};
}

function removePromise(promise) {
return {
type: REMOVE_PROMISE,
promise: promise,
};
}

function startFetchingCard() {
return {
type: START_FETCHING_CARD
Expand All @@ -29,9 +45,13 @@ function fetchCard() {
return (dispatch, getState) => {
dispatch(startFetchingCard());
let url = apiPath() + "/card/" + getState().page.cardSlug;
return fetch(url)
let promise = fetch(url)
.then(response => response.json())
.then(json => dispatch(finishFetchingCard(json)));
.then(json => {
dispatch(finishFetchingCard(json));
dispatch(removePromise(promise));
});
return dispatch(addPromise(promise));
};
}

Expand Down
12 changes: 12 additions & 0 deletions frontend/src/redux/reducers.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import {
ADD_PROMISE,
REMOVE_PROMISE,
START_FETCHING_CARD,
FINISH_FETCHING_CARD,
NAVIGATE
Expand All @@ -21,6 +23,16 @@ function navigate(state, path) {

export default function root(state = {}, action) {
switch (action.type) {
case ADD_PROMISE:
return {
...state,
promises: [...state.promises, action.promise]
};
case REMOVE_PROMISE:
return {
...state,
promises: state.promises.filter(p => p !== action.promise)
};
case START_FETCHING_CARD:
return {
...state,
Expand Down
14 changes: 12 additions & 2 deletions frontend/src/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ import App from './components/app'
import {navigate} from "./redux/actions";
import configureStore from "./redux/configureStore";

function hasPromises(state) {
return state.promises.length > 0
}

export default function render(initialState, url) {
export default async function render(initialState, url) {
const store = configureStore(initialState);
store.dispatch(navigate(url));

Expand All @@ -16,8 +19,15 @@ export default function render(initialState, url) {
</Provider>
);

let content = renderToString(app);
renderToString(app);

let preloadedState = store.getState();
while (hasPromises(preloadedState)) {
await preloadedState.promises[0];
preloadedState = store.getState()
}

let content = renderToString(app);

return {content, preloadedState};
};

0 comments on commit f295955

Please sign in to comment.