I am using react router v4 and I'm trying to wrap my head around a react-router / redux / HOC related issue. I have a higher order component working. The HOC itself is connect()
-ed to redux store. This approach works perfectly if I wire it up in a <Route />
via a component
prop: <Route path="/profile" component={ withAuth(Profile) } />
does work.
However, when I try to do the same with a <Route />
and a render prop it does not work: <Route path="/profile" render={ () => withAuth(Profile) } />
The console throws "Route.render(): A valid React element (or null) must be returned. You may have returned undefined, an array or some other invalid object.
" It does work when I omit the HOC: <Route path="/profile" render={ () => <Profile /> } />
so I suspect a problem with the HOC but I can't find it.
The reason I'm trying to use render
is I'd like to pass additional props to the HOC. Besides it bugs me that I can't find the bug.
Can anybody with a fresh eye have a look and put me on the right path? Thanks!
/* === app.js === */
import React, { Component } from 'react';
import { Route } from 'react-router-dom';
import { Provider } from 'react-redux';
import Header from './header';
import Home from './home';
import Content from './about';
import Profile from './profile';
import withAuth from './withAuth';
import store from '../reducers/store';
export default class App extends Component {
render() {
return (
<Provider store={store}>
<div className="mdl-grid">
<Header />
<main className="mdl-layout__content">
<div className="page-content">
<Route path="/" exact component={Home} />
<Route path="/about" component={Content} />
<Route path="/profile" render={ () => withAuth(Profile) } />
</div>
</main>
</div>
</Provider>
)
}
}
/* === withAuth.js (Higher order component) === */
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { Redirect } from 'react-router-dom';
const HOC = WrappedComponent => {
return class extends Component {
render() {
if (this.props.auth) {
return <WrappedComponent authenticated={this.props.auth} {...this.props} />
} else {
return <Redirect to="/" />
}
}
}
}
function mapStateToProps({ auth }) {
return { auth };
}
export default WrappedComponent => connect(mapStateToProps)( HOC(WrappedComponent) );
The reason it doesn't work is because, here
render is actually assigned a function withAuth and not the returned value. What you need to do is
The difference between
and
is that in the first case its an arrow function that is bound to the context. Whereas in the second case its a function returning a component