erikras / react-redux-universal-hot-example

A starter boilerplate for a universal webapp using express, react, redux, webpack, and react-transform
MIT License
11.99k stars 2.5k forks source link

Access to Redux store from another module? #1104

Open richb-hanover opened 8 years ago

richb-hanover commented 8 years ago

A question about structuring my code. I have a module that connects to an external server and supplies updates that want to go into the Redux store. It must run on the server, and I am (successfully) initializing and starting the module from server.js, right before the call to server.listen()

I want that module to be able to send actions to the Redux store. I think I see how to handle all the reducers, etc. My question:

What's the "right way" to make my module aware/able to access the redux store?

(I see that app.use() in server.js calls createStore(). I thought about passing store as a parameter to my module's init(), but that seems to be called with every request...)

Update: Oh, wait. It could be worse than I thought. The store is constantly being updated/replaced - how can my module continually track the current store? Thanks.

tearsofphoenix commented 8 years ago

@richb-hanover It's a piece of cake:

export function someAction() {
   return (dispatch, getState) => {
        const state = getState(); // get state from store here,
        dispatch(otherAction()).then(.....); //dispatch actions here
   };
}
richb-hanover commented 8 years ago

@tearsofphoenix Thanks for the speedy response, but that's not what I meant to ask. I think my question is more one of mechanics than deep understanding...

Let's say my module (named 'ticker-updates.js') receives intermittent stock ticker updates every few seconds. Their arrival is independent of actions from the GUI, but should obviously update the GUI as required.

My understanding is that "all I need to do" is create an action each time an update arrives, and pass it to the dispatch() method of Redux. Of course, I need to create reducers and components that handle the data as well. My question revolves around what the 'ticker-updates.js' file should look like:

Thanks.

Update: I considered "passing store to the non-Redux code" as suggested in the second answer on http://stackoverflow.com/questions/31970675/where-do-long-running-processes-live-in-a-react-redux-application. But the createStore() call is in the server.js app.use() call, and seems to be called on every page hit...

smontlouis commented 8 years ago

Hi @richb-hanover, Did you think of exporting the store once it's created in server.js, then use store.dispatch() in your ticker-updates.js ?

And yeah, the createStore is called on every page hit (understand every "hard refresh", not every javascript route change), so it should not be an issue. You can still pass store.dispatch() as a param when you init your module.

richb-hanover commented 8 years ago

I guess I am not thinking about it properly, but I don't see how to meld your advice into the current react-redux-universal-hot-example structure. I tried the following, but calling tickerInit() from the server.js gives console.log() output tickerStore is {} in my code:

Any thoughts about how I should structure the code? Thanks!

server.js

import tickerInit from './utils/ticker-updates.js';
let myStore = null;  // init to null

// in the existing app.use() function...
  ...
  const store = createStore(history, client);

  // start the ticker module once the store has been initialized
  if (myStore === null) {   // myStore is a global to the server.js file
    myStore = store;        // keep local copy so we only call tickerInit() one time
    tickerInit(store);      // pass store to the ticker-updates.js module
  }

ticker-updates.js

let tickerStore = null;         // initially set to null within the module

export default function tickerInit(store) {
  tickerStore = store;          // save as a variable in the module
  console.log(`tickerStore is ${JSON.stringify(tickerStore)}`);

  // an action to update a stock ticker
  const action = { type: 'STOCK_UPDATE', ticker: 'GOOG', value: 753.00 };

  // call the store's dispatch every 1000 msec
  setInterval(() => { tickerStore.dispatch(action); }, 1000 );
}