René Dahl Hansen
René Dahl Hansen

Reputation: 89

React Router id as parameter

In my app.js component i have a array called "recipes", it have to elements i like to render these elements in the router thought a id. The App component shound render it thouth the recipe component.

I have some code here, but it does not work properly. I have tried all night long, but i cant find the error. I am new to react so maybe you can see the mistake i cant.

App.js

    import React, { Component } from "react";
import "./App.css";
import Recipes from "./components/Recipes";
import { Router } from "@reach/router";
import Recipe from "./components/Recipe ";
import Nav from "./components/Nav";
import About from "./components/About";

class App extends Component {
  constructor(props) {
    super(props);

    this.state = {
      recipes: [
        {
          id: 1,
          title: "Drink",
          image: "https://picsum.photos/id/395/200/200"
        },
        { id: 2, title: "Pasta", image: "https://picsum.photos/id/163/200/200" }
      ]
    };
  }

  getRecipe(id) {
    //Number(id)

    return this.state.recipes.find(e => e.id === Number(id));
  }

  render() {
    return (
      <React.Fragment>
        Recipes
        {/*Sending the props from this component to the recipes component so it can be rendered there. And shown here
               <Recipes recipes={this.state.recipes}></Recipes>
          */}
        <Nav></Nav>
        <Router>
          <About path="/about"></About>
          <Recipe
            path="/recipe/:id"
            loadRecipe={id => this.getRecipe(id)}
          ></Recipe>
        </Router>
      </React.Fragment>
    );
  }
}

export default App;

Recipe.js

import React, { Component } from "react";

class Recipe extends Component {
  constructor(props) {
    super(props);

    this.state = {
      // See App.js for more details. loadRecipe is defined there.
      recipe: this.props.loadRecipe(this.props.id)
    };
  }

  render() {
    // In case the Recipe does not exists, let's make it default.
    let title = "Recipe not found";

    // If the recipe *does* exists, make a copy of title to the variable.
    if (this.state.recipe) {
      title = this.state.recipe.title;
    }

    return (
      <React.Fragment>
        <h1>The recipe:</h1>
        <p>{title}</p>
        {/* TODO: Print the rest of the recipe data here */}
      </React.Fragment>
    );
  }
}

export default Recipe;

I have these two components, i dont know whats wrong, i dont get any error.

Upvotes: 6

Views: 43884

Answers (1)

Austin Wolfe
Austin Wolfe

Reputation: 389

We need to add a Route component somewhere to get the functionality that you are expecting. You need to do one of two things. Either make the recipe component a Route component, or leave it as is and wrap it in a Route Component and use the render prop.

const Recipe = (props) => {
  <Route {...props}>
     // This is where your actual recipe component will live
  </Route>
}

Then you will be able to

<Recipe
  path="/recipe/:id"
  loadRecipe={this.getRecipe}>
</Recipe>

for the loadRecipe portion, you may want to just pass the function down and then use it in the Recipe component. You should get the id from the Route component.

or

  <Route path="/recipe/:id" render={()=> <Recipe passDownSomething={this.state} />} />

Once you make this change, you be able to use the trusty console.log to figure out what you are getting props wise and make the necessary adjustments.

Upvotes: 10

Related Questions