Skip to content

Commit

Permalink
SAVEPOINT
Browse files Browse the repository at this point in the history
  • Loading branch information
tsubik committed Nov 14, 2024
1 parent 2ccfdb4 commit 62a5ba9
Show file tree
Hide file tree
Showing 5 changed files with 111 additions and 97 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
"moveto": "^1.8.1",
"next": "14",
"next-http-proxy-middleware": "^1.2.6",
"next-redux-wrapper": "^4.0.1",
"next-redux-wrapper": "8",
"normalize.css": "^8.0.1",
"prop-types": "^15.8.1",
"rc-tooltip": "6.2.0",
Expand Down
173 changes: 85 additions & 88 deletions pages/_app.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import React from 'react';
import React, { useEffect } from 'react';
import { Provider } from 'react-redux';
import App from 'next/app';
import Router from 'next/router';
import withRedux from 'next-redux-wrapper'; // eslint-disable-line import/extensions
import { IntlProvider } from 'react-intl';

import { setUser } from 'modules/user';
Expand All @@ -17,7 +15,7 @@ import PageViewTracking from 'components/layout/pageview-tracking';
import Error from 'pages/_error';

import { getSession } from 'services/session';
import { makeStore } from 'store';
import wrapper from 'store';

import 'css/index.scss';

Expand Down Expand Up @@ -50,69 +48,13 @@ if (process.env.NODE_ENV !== 'production') {
console.error("Application is ignoring warnings:", IGNORE_WARNINGS);
}

class MyApp extends App {
static async getInitialProps({ Component, ctx }) {
const { asPath, pathname, query, isServer, req, res, store, locale, defaultLocale } = ctx;
const state = store.getState();
const url = { asPath, pathname, query };
let user = null;
let language = locale || 'en';

if (isServer) {
const session = await getSession(req, res);
user = session.user;
} else {
user = state.user;
}

const languageFile = language === 'zh' ? 'zh_CN' : language;
// for production env use precompiled language json files (see formatjs compile)
const languageFolder = process.env.NODE_ENV === "production" ? 'compiled/' : '';
const messages = await import(`lang/${languageFolder}${languageFile}.json`);

await loadLocales[language]();

store.dispatch(setLanguage(language));
store.dispatch(setUser(user));

const requests = []
if (!isServer) {
if (!state.operators.data.length) {
requests.push(store.dispatch(getOperators()));
}
if (!state.countries.data.length) {
requests.push(store.dispatch(getCountries()));
}
}
await Promise.all(requests);
const isServer = typeof window === 'undefined';

const pageProps = Component.getInitialProps ?
await Component.getInitialProps({ ...ctx, url }) :
{};

if (pageProps.errorCode && isServer) {
res.statusCode = pageProps.errorCode;
}
if (pageProps.redirectTo) {
if (isServer) {
const localePrefix = locale === defaultLocale || pageProps.redirectTo.startsWith('/' + locale) ? '' : '/' + locale;
let redirectPermanent = true;
if (pageProps.redirectPermanent == false) {
redirectPermanent = false;
}
res.writeHead(redirectPermanent ? 301 : 302, { Location: localePrefix + pageProps.redirectTo });
res.end();
} else {
Router.replace(pageProps.redirectTo);
}
return {};
}

return { pageProps, language, messages, defaultLocale, url };
}
const MyApp = ({ Component, ...rest }) => {
const { store, props } = wrapper.useWrappedStore(rest);
const { pageProps, defaultLocale, language, messages, url } = props;

async componentDidMount() {
const { store } = this.props;
useEffect(async () => {
const state = store.getState();

if (!state.operators.data.length) {
Expand All @@ -125,34 +67,89 @@ class MyApp extends App {
// TODO: maybe move this to dedicated component that would load toastr with its reducer
const { reducer: toastrReducer } = await import('react-redux-toastr');
store.injectReducer('toastr', toastrReducer);
}, []);

if (pageProps.errorCode) {
return <Error statusCode={pageProps.errorCode} url={url} />;
}

return (
<IntlProvider
locale={language}
messages={messages}
textComponent="span"
defaultLocale={defaultLocale}
>
<Provider store={store}>
<>
<GoogleTagManager />
<HotJar />
<PageViewTracking />
<Component {...pageProps} language={language} />
</>
</Provider>
</IntlProvider>
);
}

MyApp.getInitialProps = wrapper.getInitialAppProps(store => async ({ Component, ctx }) => {
const { asPath, pathname, query, req, res, locale, defaultLocale } = ctx;
const state = store.getState();
const url = { asPath, pathname, query };
let user = null;
let language = locale || 'en';

if (isServer) {
const session = await getSession(req, res);
user = session.user;
} else {
user = state.user;
}

render() {
const { Component, pageProps, store, defaultLocale, language, messages, url } = this.props;
const languageFile = language === 'zh' ? 'zh_CN' : language;
// for production env use precompiled language json files (see formatjs compile)
const languageFolder = process.env.NODE_ENV === "production" ? 'compiled/' : '';
const messages = await import(`lang/${languageFolder}${languageFile}.json`);

if (pageProps.errorCode) {
return <Error statusCode={pageProps.errorCode} url={url} />;
await loadLocales[language]();

store.dispatch(setLanguage(language));
store.dispatch(setUser(user));

const requests = []
if (!isServer) {
if (!state.operators.data.length) {
requests.push(store.dispatch(getOperators()));
}
if (!state.countries.data.length) {
requests.push(store.dispatch(getCountries()));
}
}
await Promise.all(requests);

const pageProps = Component.getInitialProps ?
await Component.getInitialProps({ ...ctx, url }) :
{};

return (
<IntlProvider
locale={language}
messages={messages}
textComponent="span"
defaultLocale={defaultLocale}
>
<Provider store={store}>
<>
<GoogleTagManager />
<HotJar />
<PageViewTracking />
<Component {...pageProps} language={language} />
</>
</Provider>
</IntlProvider>
);
if (pageProps.errorCode && isServer) {
res.statusCode = pageProps.errorCode;
}
if (pageProps.redirectTo) {
if (isServer) {
const localePrefix = locale === defaultLocale || pageProps.redirectTo.startsWith('/' + locale) ? '' : '/' + locale;
let redirectPermanent = true;
if (pageProps.redirectPermanent == false) {
redirectPermanent = false;
}
res.writeHead(redirectPermanent ? 301 : 302, { Location: localePrefix + pageProps.redirectTo });
res.end();
} else {
Router.replace(pageProps.redirectTo);
}
return {};
}

}
return { pageProps, language, messages, defaultLocale, url };
});

export default withRedux(makeStore)(MyApp);
export default MyApp;
1 change: 0 additions & 1 deletion pages/about.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import Html from 'components/html';

class AboutPage extends React.Component {
static async getInitialProps({ url, store }) {

await Promise.all([
store.dispatch(getPartners()),
store.dispatch(getDonors()),
Expand Down
24 changes: 21 additions & 3 deletions store.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,34 @@
import { createStore, combineReducers, applyMiddleware, compose } from 'redux';
import thunk from 'redux-thunk';
import * as staticReducers from 'modules';
import { createWrapper, HYDRATE } from 'next-redux-wrapper';

function createReducer(asyncReducers) {
return combineReducers({
const combinedReducers = combineReducers({
...staticReducers,
...asyncReducers
});

const allReducers = (state, action) => {
if (action.type === HYDRATE) {
const nextState = {
...state,
...action.payload,
};
return nextState;
}
else {
return combinedReducers(state, action);
}
}

return allReducers;
}

export const makeStore = (initialState = {}) => {
const makeStore = (context) => {
const store = createStore(
createReducer(),
initialState,
{},
compose(
applyMiddleware(thunk),
/* Redux dev tool, install chrome extension in
Expand All @@ -31,3 +47,5 @@ export const makeStore = (initialState = {}) => {
return store;
}

export default createWrapper(makeStore);

8 changes: 4 additions & 4 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4187,10 +4187,10 @@ next-http-proxy-middleware@^1.2.6:
"@types/http-proxy" "1.17.3"
http-proxy "^1.18.1"

next-redux-wrapper@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/next-redux-wrapper/-/next-redux-wrapper-4.0.1.tgz#70f2d83b5bd0fb07ec19e6e70bea6b179d295fd7"
integrity sha512-aj9s4VT062hvrU8k2OQevf6iffHSIXpDXtIA8xbLzfpP94h3w7vZCmAJmbmfq3rXignqJT3KG44GODwsCQmdsA==
next-redux-wrapper@8:
version "8.1.0"
resolved "https://registry.yarnpkg.com/next-redux-wrapper/-/next-redux-wrapper-8.1.0.tgz#d9c135f1ceeb2478375bdacd356eb9db273d3a07"
integrity sha512-2hIau0hcI6uQszOtrvAFqgc0NkZegKYhBB7ZAKiG3jk7zfuQb4E7OV9jfxViqqojh3SEHdnFfPkN9KErttUKuw==

next@14:
version "14.2.16"
Expand Down

0 comments on commit 62a5ba9

Please sign in to comment.