Search code examples
reactjswebsocketreduxreact-reduxredux-thunk

React Redux - state undefined on first render



For my client I'm creating something like quiz web app in react with redux based on websockets (socket.io) with a huge, very unique data. No user interaction, just presentation layer. It works like this: I get websocket event with url to my layout and payload data, and then I render given url and fire redux action with data as argument, which becomes app's state. Simple as that. BUT I noticed that on first render initial state is loading, not given from websocket as argument to action. As I said data I get is huge and unique so I didn't want declare in reducer something like this:

pageData: {
    assets: [],
    questions: [],
    details: []

And so on. It's much more complicated btw it's just an example.
Instead of this I made something like this:

pageData: {}

And I was hoping that on view (using connect) I can get this data like this:

this.props.view.pageData.questions

But then it turned out that I can not get this because it's undefined on first render. So my questions are:

  • Is there a way to access to this data on first render without declaring whole structure?
  • If not, should I reconstruct given data in reducer?

    • Should I then create reducers for each page (there are like over 20 views with unique data)

Of course I can declare everything in reducers but I feel it's very hard to maintain so much data.
But you know, maybe I'm just too lazy and I should declare initial state for each page and this question does not have sense ;).


Solution

  • I think you may have a few options here:

    1. Define fallback data in your components if undefined
    2. Don't render your page (or components) until you have received the data
    3. Define your initialState explicitly as you already suggested

    All or most your components expect or should expect data of a certain kind and in a certain format. For this reason, laying out the structure beforehand (#3) seems to be most appropriate. Ask yourself this: would my app still display correctly if the format of the web socket event data changes?

    To answer your questions specifically:

    Is there a way to access to this data on first render without declaring whole structure?

    Yes, you could use the || operator in your bindings to fall back (#1) to an empty array or object or value. Example <MyComponent listOfItems={this.props.items || []}. This effectively creates an empty state, however, IMO this should be standardized in the reducer/store with initialState.

    Should I then create reducers for each page[?]

    Not necessarily a reducer for each page, but a store with all pertinent data to your application. It is hard to say for sure without knowing more about the architecture of your app, but keeping small, well defined chunks of information is generally easier than one big blob.

    I strongly advocate defining your data beforehand. It might sound cumbersome at first, but it will pay off greatly and helps others understand what the app might look like with live data.