Q:

Render functional component that is reliant on useState, on condition

I am new to react, hooks and functional components.
I have a Dashboard component wrapped in a context provider Store, when Store loads it establishes a socket connection, the server then sends the required DB (allChats) data to the client, which is loaded by a reducer dispatch.
In Dashboard i get the keys (topics) from allChats, i have a list that's populated by a key (activeTopic) value in topics.
activeTopic is hooked with useState, initial value is supposed to be the first key entry in topics.
Problem is Dashboard renders before the client recieves the DB data, i need to render Dashboard either after the DB payload is recieved or render a placeholder until allChats is updated in the Context provider and re-render is triggered.
I can't conditionally set the useState hook, and when i try to return render contents conditionally it throws undefined errors because the variable assignments are happening after the render is triggered.
App.js
import Dashboard from "./Dashboard";
import Store from './Store'

function App() {

  return (
    <div className="App">
      <Store>
        <Dashboard />
      </Store>
    </div>
  );
}

export default App;

Store.js
let socket;

function reducer(state, action) {
  switch(action.type) {
    //Replace state with DB payload
    case 'LOAD_MESSAGES':
      return action.payload
    default:
      return state
  }
}

export default function Store(props) {
  //Hook reducer for DB data
  const [allChats, dispatch] = React.useReducer(reducer, {});

  if (!socket) {
    socket = io(':3001');
    //listen for DB data from server upon connection
    socket.on('initialize', function(msg) {
      dispatch({type: 'LOAD_MESSAGES', payload: msg})
    })
  }

  return (
  <CTX.Provider value={{allChats}}>
    {props.children}
  </CTX.Provider>
  )
}

Dashboard.js
export default function Dashboard() {

  const classes = useStyles();
  //Import DB data
  const {allChats} = React.useContext(CTX);
  //Get keys from DB data
  const topics = Object.keys(allChats);
  //Hook activeTopic, initialise with the first key entry
  const [activeTopic, changeActiveTopic] = React.useState(topics[0]);

  return (
    <div>
      <div>
        {
        //populate list with messages from activeTopic key of DB data
        allChats[activeTopic].map((chat, i) => (
            <div key={i}>
                <Chip label={chat.from} className={classes.chip}/>
                <Typography variant='h5' gutterBottom>{chat.msg}</Typography>
            </div>)) 
        }
      </div>
    </div>
  )
}

I am obviously missing the key concepts of the react, context and hook lifecycle. I don't want to hack out a solution i want to be able to handle it the proper way.
I would really appreciate the help, thank you.

A:

I would add a isLoaded flag to the allChats reducer.  Then, you can use that in the dashboard to show <div>loading</div> or the loaded chat view above.

