Reputation: 443
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
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
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
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