2

I'm creating a webapp and I will have multiple 'specs' in the front end, the number of which is determined via a response from a backend database. What I want is to create a React Route for each spec. I want to do this dynamically, that way if I add some more specs in the backend database then I won't have to add a bunch of hard coded routes in the front end to match.

I'm using Jumpsuit as a React/Redux wrapper. For the specs, I query the backend and store the specs in an array in state. I can get this spec array from state no problems, however, if I try to dynamically create routes based on this spec array (one route for each spec) then it doesn't create them.

Below is my code (minus imports). At the moment I just tried giving each dynamic route the same 'Spec' component, just a very simple Component which renders a few words. I created some buttons that navigate to these routes on click, but when I click them the url changes to the correct route, but the page doesn't change at all. And if I print my main component's props to the console and look at the routes, I can see the dynamic ones aren't there. I'm not getting any console errors.

export default Component({

    componentDidMount() {
        // Check if the specs need to be loaded
        if (this.props.specs.length == 0) {
            axios.get('/getspecs')
                .then((specs) => {
                    // Load specs into state
                    QuizList.loadSpecs(specs.data.facet_counts.facet_fields.spec.filter((val, i) => {return (i%2==0)}));
                })
                .catch((error) => {
                    console.log(error);
                });
        }
    },

    loadSpecRoutes() {
        // Loop through specs array in state and create route for each
        return this.props.specs.map((spec, i) => {
            return(
                <Route path={`/spec/${spec}`} component={Spec} />
            );
        });
    },

    render () {
        return (
            <Router history={browserHistory}>
              <Route path='/' component={App}>
                <IndexRoute component={Home}/>
                <Route path='/account' component={Account}/>
                <Route path='/quizzes' component={QuizRoot}/>
                {this.loadSpecRoutes()} <-- where I want to load routes
              </Route>
            </Router>
        );
    }
}, (state) => ({
    auth: state.user.auth,
    specs: state.quizList.specs
}))

Not sure if I'm just going about this all the wrong way, but how do I create a Route component for each value in a state array?

1 Answer 1

5

Instead of creating a route for each spec, you can actually use a dynamic route and create a wrapper components that can dynamically render your spec. The wrapper can do very little things, even just a div tag. Or it can be quite a template, like a blog page, that has everything styled except the article content. This depends on how different each of your spec is

Now we look at the route, it can be simplified to something like

<Router history={browserHistory}>
  <Route path='/' component={App}>
    <IndexRoute component={Home}/>

    <Route path='/account' component={Account}/>
    <Route path='/quizzes' component={QuizRoot}/>
    <Route path='/specs/:spec' component={Spec} />
  </Route>
</Router>

Then in the Spec Component, you can do things like

class Spec extends Component {
  render () {
    const {spec} = this.props.params

    switch (spec) {
      case 'spec1':
        return <SpecTypeA />
      case 'spec2':
        return <SpecTypeB />
      default:
        return <GeneralSpec />
    }
  }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.