Robin Robin - 1 year ago 360
React JSX Question

React Router v4 with babel gives error with multiple routes

I'm trying to make react-router v4 ("react-router": "^4.0.0-2") work in my project, and have tried to implement it based on the quick start example. I am however unable to make it work with multiple routes. I keep getting:

invariant.js:38 Uncaught Invariant Violation: MatchProvider.render(): A valid React element (or null) must be returned. You may have returned undefined, an array or some other invalid object.

My code is as follows

class Router extends Component {
render() {
let returnVal = (<BrowserRouter>
<Match pattern="/" component={FrontPage} />
<Match pattern="/home" component={Home} />
return returnVal;

export default Router;

The code that is generated by webpack and babel looks as follows

var Router = function (_Component) {
_inherits(Router, _Component);

function Router() {
_classCallCheck(this, Router);

return _possibleConstructorReturn(this, (Router.__proto__ || Object.getPrototypeOf(Router)).apply(this, arguments));

_createClass(Router, [{
key: 'render',
value: function render() {
var returnVal = _react2.default.createElement(
_react2.default.createElement(_reactRouter.Match, { pattern: '/', component: _FrontPage2.default }),
_react2.default.createElement(_reactRouter.Match, { pattern: '/home', component: _Home2.default })
return returnVal;

return Router;

I've set a debugger statement where the error is thrown, and I see the following:

enter image description here

Where you can see that the react element returned is an array, as the error message implies that it could be. And the props identify the offending components as the routes inside my BrowserHistory component.

If I remove one of the routes, such that there is only one element inside the BrowserHistory component, it renders correctly. If I have a Match and a Miss component, it also gives the error.

I'm not exactly sure where to start looking, which library the error occurs in. As far as I can see the output code is valid, and I don't know why it doesn't render correctly.

If anyone knows how to fix it, it would be greatly appreciated.

Answer Source

The stuff inside a Router or MatchProvider has to be wrapped inside a div.

Such as the following

    <Match exactly pattern="/" component={FrontPage} />
    <Match pattern="/home" component={Home} />

MatchProvider returns it's children directly, and as such it can only have one child. It could also be solved by modifying the MatchProvider.js inside the React-router library to return

return _react2.default.createElement("div", null, this.props.children);

instead of

return this.props.children

if you should desire for some reason to have the routes directly under the router.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download