Created
April 10, 2018 00:12
-
-
Save fetchTe/d56750d955ff4a60ed11e6a714cbd1bd to your computer and use it in GitHub Desktop.
Revisions
-
fetchTe created this gist
Apr 10, 2018 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,230 @@ /** * So here's the redux wrapper I used to solve the problem, or at least, that is * what I think. I'm, not all to sure but maybe this will give you some insight. */ import React, { Component } from 'react'; import thunkMiddleware from 'redux-thunk'; import { Provider } from 'react-redux'; import { createLogger } from 'redux-logger'; import firebase from 'firebase'; import { applyMiddleware, compose, createStore, } from 'redux'; import { getFirebase, reactReduxFirebase, } from 'react-redux-firebase'; import { middleware as memoizationMiddleware } from './redux-memoization'; import reducer from 'reducers/'; // import firebaseConfig from 'constants/firebase.config'; const firebaseConfig = { apiKey: process.env.API_KEY, authDomain: process.env.AUTH_DOMAIN, databaseURL: process.env.DATABASE_URL, storageBucket: process.env.STORAGE_BUCKET, }; /** * Base Firebase App conifg consumed by redux-wrapper */ const firebaseApp = () => { // check if firebase instance exsits return !firebase.apps.length ? firebase.initializeApp(firebaseConfig) : firebase.app(); }; /** * helper to create redux store for Next.js isomorphic apps * @param {---} options.initStoreReducer → init reducers * @param {---} options.initialState → init state * @param {---} options.req → server req * @return {---} → init store */ const initStore = ({initStoreReducer, initialState, req}) => { //readux middleware const middlewares = [ //memeomizer → @note not important to the problem memoizationMiddleware, //Pass getFirebase function as extra argument //to get the most out of thunks thunkMiddleware.withExtraArgument(getFirebase), ]; if (process.env.NODE_ENV !== 'production') { middlewares.push(...[ //simple logger createLogger({ collapsed: true }), ]); } // react-redux-firebase config const reactReduxFirebasefConfig = { userProfile: 'users', // enableLogging: true, enableLogging: false, enableRedirectHandling: false, updateProfileOnLogin: true, setProfilePopulateResults: true, // profileParamsToPopulate: [{ child: 'role', root: 'roles' }], // profileParamsToPopulate: [ // 'reservations', // 'email', // 'reservations:users', // 'contacts:users', // ], }; //shared store args const initStoreArgs = [initStoreReducer, initialState]; const composeArgs = [ reactReduxFirebase(firebaseApp(), reactReduxFirebasefConfig), applyMiddleware(...middlewares), ]; // Always make a new store if server if (!process.browser) { req = req || {}; req._store = createStore( ...initStoreArgs, compose(...composeArgs), ); return req._store; } // Memoize store if client if (!window.store) { const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose; window.store = createStore( ...initStoreArgs, composeEnhancers(...composeArgs), ); } return window.store; }; /** * higher order component (HOC) to set up the redux store for components * to share here: https://github.com/zeit/next.js/issues/424 */ export default (WrappedComponent) => { return class EnhancedComponent extends Component { static displayName = `withRedux(${WrappedComponent.displayName || WrappedComponent.name}`; static async getInitialProps(context) { const { req } = context; const isServer = !!req && typeof window === 'undefined'; const store = initStore({ initStoreReducer: reducer, initialState: undefined, req: req, }); //client set cookies let cookies = req && req.headers && req.headers.cookie || {}; if (typeof cookies === 'string') { const cookie = require('cookie'); cookies = cookie.parse(cookies); } //pass init props to getInitProps wrapped component for ssr ops let wrappedInitialProps = {}; if (WrappedComponent.getInitialProps) { context = { ...context, dispatch: store.dispatch, getState: store.getState, initialState: store.initialState, initStoreReducer: reducer, isServer: store.isServer, }; wrappedInitialProps = await WrappedComponent.getInitialProps(context); } //Check for localStorge store cache and pass to cache populate const localStorageStore = process.browser && localStorage && localStorage.store ? JSON.parse(localStorage.store) : {}; //→ return { ...wrappedInitialProps, cookies, initialState: store.getState(), isServer, localStorageStore, }; } constructor(props) { super(props); this.store = initStore({ initStoreReducer: reducer, initialState: props.initialState, req: null, }); } render() { return ( <Provider store={this.store}> <WrappedComponent {...this.props} /> </Provider> ); } }; }; /******************************************************************************* ******************************************************************************* ******************************************************************************* * Here's an example use with a /page dir root component */ import React, {Component} from 'react'; import log from 'loglevel'; import { compose, withProps, } from 'recompose'; import Layout from 'components/Layout/Layout'; import enhancedPage from 'containers/enhancedPage'; import Bookings from 'components/Bookings/Bookings'; //@THE IMPORTANT HOC MAGIC THAT HOPEFULLY FIXES YOUR PROBLEMS import withRedux from 'lib/redux-wrapper'; class BookingsPage extends Component { render() { log.info('pages/bookings.js:::RENDER'); return( <Layout {...this.props}> <Bookings /> </Layout> ); } } export default compose( withRedux, withProps({ title: 'Bookings', }), enhancedPage, )(BookingsPage);