Reputation: 764
I am new to ReactJS and sorry if this question was asked before, I don't know where to start.
I followed the Auth guidelines in: https://reacttraining.com/react-router/web/example/auth-workflow
I am using react-router to handle navigation with ReactJS, I have an index.js file that handles the navigation and includes:
import {BrowserRouter, Redirect, Route} from 'react-router-dom';
import Auth from './components/Auth';
const PrivateRoute = ({ component: Component, ...rest }) => (
<Route {...rest} render={props => (
Auth.authenticate((auth) => {
if (auth) {
(<Component {...props}/>)
}
else {
(<Redirect to={{
pathname: '/',
state: { from: props.location }
}}/>)
}
})
)}/>
)
const App = () => (<BrowserRouter>
<div>
{/* PUBLIC */}
<Route path={'/'} exact component={Inicio}/>
<Route path={'/login'} component={Login}/>
{/* PRIVATE */}
<PrivateRoute path="/dashboard" component={Dashboard}/>
</div>
</BrowserRouter>);
ReactDOM.render(<App/>, document.getElementById('root'));
Navigates fine, but the Authentication in Auth.authenticate((auth).. isn't working properly and throws an error.
It refers to a file that has the following:
import React from 'react';
import http from '../services/http';
const Auth = {
authenticate(cb) {
http.authenticate((e, auth) => {
if (auth === true) {
cb(true);
}
else {
cb(false);
}
});
}
}
export default Auth;
http.aunthenticate is a method with a callback, that works fine.
Yet I get the following error message in the console:
> The above error occurred in the <Route> component:
> in Route (created by PrivateRoute)
> in PrivateRoute (created by App)
> in MuiThemeProvider (created by App)
> in div (created by App)
> in Router (created by BrowserRouter)
> in BrowserRouter (created by App)
> in App
>
> Consider adding an error boundary to your tree to customize error
> handling behavior. Visit https://reactjs.org/docs/error-boundaries.html to learn
> more about error boundaries. react-dom.development.js:9747 Error:
> Route(...): Nothing was returned from render. This usually means a
> return statement is missing. Or, to render nothing, return null.
Any ideas? Thanks!
Upvotes: 0
Views: 453
Reputation: 1568
Your PrivateRoute
component never returns anything. Auth.authenticate((auth) =>...
this is asynchronous therefore it's the same as if your method was empty in terms of render
response. You should avoid doing that and simply have a property to detect whether or not the account is logged in or not. Per example this is how I wrote my PrivateRoute component using Facebook's Flux store.
const PrivateRoute = ({ component: Component, ...rest }) => (
<Route {...rest} render={props => (
AccountStore.loggedIn ? (
<Component {...props} />
) : (
<Redirect to={{
pathname: '/signin',
state: { from: props.location }
}} />
)
)} />
)
Here my component will always return something based off the account state being calculated prior to the rendering.
EDIT: Adding my AccountStore below for a bit more clarity on the specifics, Here I use a jwt token received after authenticatingn through a remote api and use whether or not it's set to determine if the user is logged in or not. However, it can be any property/value you pick. Could even be a class not connecting to anything and just flipping the user login status through a couple methods.
import Immutable from 'immutable';
import { ReduceStore } from 'flux/utils';
import AccountActionTypes from './AccountActionTypes';
import CoreDispatcher from '../CoreDispatcher';
import LocalStorage from '../../io/LocalStorage';
class AccountStore extends ReduceStore {
constructor() {
super(CoreDispatcher);
this._jwt = LocalStorage.getItem('jwt');
}
getInitialState() {
return Immutable.OrderedMap({
jwt: this._jwt,
});
}
reduce(state, action) {
switch (action.type) {
case AccountActionTypes.USER_DETAILS_IN:
console.log('user details in');
this._user = action.user;
return state.set('user', this._user);
case AccountActionTypes.USER_LOGGED_IN:
this._jwt = action.jwt;
return state.set('jwt', this._jwt);
case AccountActionTypes.USER_LOGGED_OUT:
this._jwt = null;
return state.set('jwt', this._jwt);
default:
return state;
}
}
get jwt() {
return this._jwt;
}
get loggedIn() {
return !!this._jwt;
}
}
export default new AccountStore();
More details to use Flux Stores and Dispatcher there: https://facebook.github.io/flux/
Upvotes: 2
Reputation: 175
It loos like a simple syntax error:
const Auth = {
authenticate(cb) {
http.authenticate((e, auth) => {
if (auth === true) {
cb(true);
}
else {
cb(false);
}
});
}
}
You need to define Auth
as a valid React component (either a class or function). What you have there is not a valid class, function, or object.
More importantly if Auth
is not rendering some jsx then it should not be a React component. HTTP requests should be defined as a class method, and called inside of a life-cycle hook, most commonly componentDidMount()
. Article explaining how to make AJAX requests in react.
Upvotes: 0