Vernon
Vernon

Reputation: 443

What's the recommended place to fetch user data using Redux when app starts?

I'm currently building a dashboard using Redux and React. I'm also implementing react-router and redux-router to redirect users when they're not logged in.

I'm not exactly sure what the recommended place is to fetch user data once the app starts. I would only like to fetch the user if a cookie is present (we're not going to use SSR).

What would be the best moment to check for the presence of the cookie and fetch the user data (and update the app's state)?

Because some routes shouldn't be available for non-authenticated users, I believe authentication should be checked in the router. However, I'm not sure what would be the best place to do this (maybe onEnter)?

Help would be appreciated!

Thanks.

Upvotes: 5

Views: 2168

Answers (3)

Vernon
Vernon

Reputation: 443

I believe this Stack Overflow answer is what I was looking for: Where do I fetch initial data from server in a React Redux app?

There's indeed no need for components to be involved while I'm just fetching initial state.

Upvotes: 3

Ananth
Ananth

Reputation: 797

It is best suggested to put your api calls along with other actions. https://github.com/reactjs/redux/issues/291 gives a nice explanation for the same.

Upvotes: 2

Sergio Flores
Sergio Flores

Reputation: 5427

I don't know what's your backend but I used to print the initial state (user data, initial config, etc.) in the HTML as a javasscript variable and the use it as the initial state for redux:

MainLayout.jsx (this runs in the back)

'use strict';
const React = require('react');
const Component = React.Component;
const PropTypes = React.PropTypes;
class MainLayout extends Component {
    render() {
        const assets = this.props.assets;
        const initialState = {
            entities: {
                users: {}
            },
            authentication: null
        };
        if (this.props.session) {
            initialState.entities.users[this.props.session.id] = this.props.session;
            initialState.authentication = {};
            initialState.authentication.id = this.props.session.id;
        }
        return (
            <html>
                <head>
                    <title>{this.props.title}</title>
                    <meta charSet="utf-8" />
                    <meta httpEquiv="X-UA-Compatible" content="IE=edge,chrome=1" />
                    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximun-scale=1.0, user-scalable=no" />
                    <link rel="stylesheet" href={assets.vendor.css} />
                    <script
                        dangerouslySetInnerHTML={{
                            __html: `window.__INITIAL_STATE__ = ${JSON.stringify(initialState)};`
                        }}
                    >
                    </script>
                </head>
                <body>
                    {this.props.children}
                    <script src={assets.vendor.js}></script>
                    {this.props.feet}
                </body>
            </html>
        );
    }
}
MainLayout.propTypes = {
    children: PropTypes.node.isRequired,
    title: PropTypes.string.isRequired,
    feet: PropTypes.object.isRequired,
    assets: PropTypes.object.isRequired,
    session: PropTypes.object
};
module.exports = MainLayout;

index.js

import React from 'react';
import { render } from 'react-dom';
import { browserHistory } from 'react-router';
import { syncHistoryWithStore } from 'react-router-redux';
import configureStore from './store';
import routes from './routes';
import App from './containers/App';

const loadauthenticationData = () => {
  if (__INITIAL_STATE__ !== null) {
    return __INITIAL_STATE__,
    };
  }
  return {};
};

const store = configureStore(loadauthenticationData());
const syncedHistory = syncHistoryWithStore(browserHistory, store);
const rootElement = document.getElementById('app');
render(
  <App
    history={syncedHistory}
    store={store}
    routes={routes}
  />,
  rootElement
);

store.js

import { createStore, applyMiddleware, compose } from 'redux';
import thunk from 'redux-thunk';
import api from './middlewares/api';
import reducers from './reducers';
const middlewaresCreateStore = compose(
  applyMiddleware(thunk, api),
  window.devToolsExtension ? window.devToolsExtension() : f => f
)(createStore);
const configureStore = (initialState) => middlewaresCreateStore(
  reducers(initialState),
  initialState
);
export default configureStore;

Upvotes: -1

Related Questions