// App.js
import * as Analytics from 'modules/analytics';
import * as Auth from 'modules/auth';
import * as Search from 'modules/search';
import * as Users from 'modules/users';
// HOC to check logged in user
function checkAuthentication(Component) {
return class extends React.Component {
state = {currentUser: null};
componentDidMount() {
api.isLoggedIn()
.then(currentUser => this.setState({ currentUser }))
.catch(() => this.setState({ currentUser: null }));
}
render() {
if (this.state.currentUser === null) return <div>Loading...</div>;
return this.state.currentUser ? (
<Component />
) : (
<Redirect noThrow to="/auth/login" />
);
}
};
}
const PROTECTED_ROUTES = [
...Analytics.routes,
...Search.routes,
...Users.routes,
].map(({component, ...props}) => ({
props,
Component: checkAuthentication(component),
}));
export default function App(props) {
return (
<Router>
{[...PUBLIC_ROUTES, ...PROTECTED_ROUTES].map(({Component, props}) => (
<Component key={props.path} {...props} /> // eslint-disable-line
))}
<Redirect noThrow from="/" to="/analytics" />
</Router>
);
}
Modules are structured like this:
src/modules
├── analytics
│ ├── components
│ │ ├── Chart.js
│ │ └── Main.js
│ ├── index.js
│ └── routes.js
├── auth
│ ├── components
│ │ └── Login.js
│ ├── index.js
│ └── routes.js
├── search
│ ├── actions.js
│ ├── components
│ │ ├── FilterDialog.js
│ │ ├── Main.js
│ │ ├── Map.js
│ │ ├── MediaItem.js
│ │ ├── MediaItemDialog.js
│ │ └── MediaSubscriber.js
│ ├── index.js
│ └── routes.js
└── users
├── components
│ ├── Main.js
│ └── UserSideSheet.js
├── index.js
└── routes.js
An example routes.js
// src/modules/search/routes.js
import Main from './components/Main';
export default [
{
path: '/search',
component: Main,
},
];