rt2zz / redux-action-buffer

Buffer Redux Actions
MIT License
79 stars 6 forks source link

Example of using react-action-buffer on v5 #14

Open githubdoramon opened 7 years ago

githubdoramon commented 7 years ago

I am not able to buffer the actions before hydration occurs on v5. Could someone give an example on how to do it?

rt2zz commented 7 years ago

I would expect it to still work, are you importing REHYDRATE from the right location (it changed in v5)? import {REHYDRATE} from 'redux-persist/lib/constants'

I have not tried redux-action-buffer alongside v5 yet, but my assumption was it would still work.

githubdoramon commented 7 years ago

I am trying this code:

  const middleware =
    applyMiddleware(createActionBuffer(REHYDRATE), thunk, logger)

  let enhancer;

  // Enable DevTools if browser extension is installed
  if (window.__REDUX_DEVTOOLS_EXTENSION__) { // eslint-disable-line
    enhancer = compose(
      middleware,
      window.__REDUX_DEVTOOLS_EXTENSION__() // eslint-disable-line
    );
  } else {
    enhancer = compose(middleware);
  }

  store = createStore(
    reducer,
    enhancer
  );

They my application does not read the store anymore... it is always at initialState

githubdoramon commented 7 years ago

It seens that no action is being consumed when I make this configuration

rt2zz commented 7 years ago

@githubdoramon sounds like REHYDRATE is the wrong constant. can you show the line where you import REHYDRATE, it should be import {REHYDRATE} from 'redux-persist/lib/constants' and the value of the imported variable should be persist/REHYDRATE

githubdoramon commented 7 years ago

@rt2zz I double checked this.... That is the exact import and the exact constant imported.

Here is the full code for the store

import { createStore, applyMiddleware, compose } from 'redux'
import thunk from 'redux-thunk'
import rootReducer from 'reducers/combined'
import logger from 'dev/logger';
import { persistStore, persistReducer } from 'redux-persist'
import storage from 'redux-persist/es/storage'
import {REHYDRATE} from 'redux-persist/lib/constants'
import createActionBuffer from 'redux-action-buffer'

const isProduction = process.env.NODE_ENV === 'production';

// Creating store
let store = null;

const storeConfig = {
  key: 'rootStore', // key is required
  storage,
}

const reducer = persistReducer(storeConfig, rootReducer)

if (isProduction) {
  // In production adding only thunk middleware

  const middleware =
    applyMiddleware(thunk)

  store = createStore(
    reducer,
    middleware
  );
} else {

  console.log(REHYDRATE);
  // In development mode beside thunk
  // logger and DevTools are added
  const middleware =
    applyMiddleware(createActionBuffer(REHYDRATE), thunk, logger)

  let enhancer;

  // Enable DevTools if browser extension is installed
  if (window.__REDUX_DEVTOOLS_EXTENSION__) { // eslint-disable-line
    enhancer = compose(
      middleware,
      window.__REDUX_DEVTOOLS_EXTENSION__() // eslint-disable-line
    );
  } else {
    enhancer = compose(middleware);
  }

  store = createStore(
    reducer,
    enhancer
  );
}

persistStore(store)

export default store

And the print of the result

image

rt2zz commented 7 years ago

hm, I am stumped. I will try to run your code later today and see what I can find.

githubdoramon commented 7 years ago

Thanks @rt2zz ... let me know if you need any information

githubdoramon commented 7 years ago

@rt2zz where you able to test it?

Thanks

githubdoramon commented 7 years ago

@rt2zz any news here?

rt2zz commented 7 years ago

ok I found the issue but I do not have an easy solution. Redux Persist v5 relies on sending out an action to get everything hooked up. Since action buffer captures this action, it prevents redux-persist from completing its initialization and hence everything hangs.

One possible solution here is to add a "pass through list" to action-buffer to let certain actions through. But this would require a breaking change to the action buffer api, and I am not sure this is a scalable approach.

Are you certain you need action buffer? I would recommend instead use import { PersistGate } from 'redux-persist/es/integration/react' to block rendering and any other actions until persist is complete. Here is a little example of that usage: https://github.com/rt2zz/redux-persist/blob/v5/docs/PersistGate.md

brownbl1 commented 7 years ago

I was just having this issue, and I think having a pass through list parameter would solve my use case. I would only be passing through one ACTION so not sure what scalability issues you had in mind. If anyone else has an idea on how to do this, I'd love to know it.

rt2zz commented 7 years ago

ya thats a good idea.

Poor use of the word scalable on my part, what I meant was I did not want to start attaching seemingly disjoint api additions. But ya a pass through makes perfect sense and could be useful for other cases as well. 👍

githubdoramon commented 7 years ago

PersistGate didn't worked.... Could you guys explain a little better how to implement the pass through list? I am working wit server side rendering and on every page refresh I can't get the previous state.

Thanks

rt2zz commented 7 years ago
import { PERSIST, REHYDRATE } from 'redux-persist/lib/constants'
actionBuffer({ passthrough: [PERSIST], breaker: REHYDRATE }, callback)

note this will break on the first rehydrate call, so I would advise on using this with a single persistReducer setup.

rt2zz commented 7 years ago

note: PersistGate would not be a drop in replacement for actionBuffer, it would require making sure all of your side-effects are triggered by component lifecycle methods rather than immediately upon loading of your bundle.

However you say you are doing SSR, in which case I would think you would want to avoid persistence entirely. I might recommend an environment variable to conditionally persist

let persistor = process.env.IS_SSR ? null : persistStore(store)

edit: note I am not personally doing SSR so I defer to someone who has more first hand knowledge on the matter. Perhaps there are idioms around this that might help.