Skip to content

Instantly share code, notes, and snippets.

@mcky
Last active August 29, 2015 14:08
Show Gist options
  • Save mcky/6e956c71c645d4657d55 to your computer and use it in GitHub Desktop.
Save mcky/6e956c71c645d4657d55 to your computer and use it in GitHub Desktop.

Can't seem to loop through <Location> components using .map as I get the following error as it's being passed as a string:

Error: Invariant Violation: Route handler should be a component or a function but got: MainPage

Array in question and the component:

[{
	'path': '/',
	'handler': 'MainPage'
},{
	'path': '/users/:userName',
	'handler': 'UserPage'
}]
var App = React.createClass({
	render: function() {
		var createRoute = function(item) {
			return <Location path={item.path} handler={item.handler} />
		}
		return (
			<Locations path={this.props.path}>
				{this.props.paths.map(createRoute)}
				<NotFound handler={NotFoundPage} />
			</Locations>
		)
	}
})
@STRML
Copy link

STRML commented Oct 30, 2014

This will work, but you can't pass your handlers as strings, you need to set the handler to the actual component that handles the route. RRC has no way of knowing what that refers to.

@mcky
Copy link
Author

mcky commented Oct 30, 2014

Any idea how? Spent ages trying associative arrays, eval() and all kinds of nonsense. Not sure if I'm missing something really obvious/just writing really bad code.

Just a bit annoying as I wrote a load of code for parsing routes/handlers from a JSON file and mapping them to express functions (to keep code and function names the same on client and server) and didn't realise it wouldn't work until I started trying to map them.

The following logs out the function reference but breaks and returns:

Error: Invariant Violation: Router should contain either Route or NotFound components as routes
var test = []
test['MainPage'] = MainPage
console.log(test['MainPage'])
return <Location path={item.path} handler={test['MainPage']} />

@STRML
Copy link

STRML commented Oct 30, 2014

Ah I see what you're trying to do. I sidestepped this in my applications by actually running the React code on the server via Webpack. You could also do the same with Browserify. So long as you feed the server the exact same data that you're feeding to the client, the prerender will be identical.

To be honest, I'm a bit murky about what JSX does when you put both an array and a single element as children of an element. I don't think it's smart enough to concatenate them into an array. Try something like this:

var App = React.createClass({
  createRoute: function(item) {
    return <Location path={item.path} handler={item.handler} />
  },
  createRoutes: function(paths) {
    return paths.map(this.createRoute).concat(<NotFound handler={NotFoundPage} />);
  },
  render: function() {
    return (
      <Locations path={this.props.path}>
        {this.createRoutes(this.props.paths)}
      </Locations>
    );
  }
})

@mcky
Copy link
Author

mcky commented Oct 30, 2014

It works! Thanks

Just had to switch item.handler to test[item.handler] - just need to convert test to module.exports now :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment