Home > Blockchain >  How to pass props through Link
How to pass props through Link

Time:12-16

Fairly new to react here. I'm making a small recipe finder app with an api. After getting the data, I'm mapping through the results and displaying them in a component. What I want to do is display the details of each recipe through another component in another route. I'm not sure how to do this. I thought I could pass the mapped recipe through Link, but it's not working. Here is what I have so far.

Index.js

import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter as Router } from 'react-router-dom';
import App from './App';


ReactDOM.render(
  <React.StrictMode>
    <Router>
    <App />
    </Router>
  </React.StrictMode>,
  document.getElementById('root')
);

App.js

import React, { useState, useEffect} from "react";
import axios from "axios";
import { BrowserRouter as Router, Routes, Route, useNavigate} from "react-router-dom";
import "./App.css";
import RecipeList from "./RecipeList";
import Recipe from "./Recipe";
import Header from "./Header";

function App() {
  const navigate = useNavigate();
  
  const [recipes, setRecipes] = useState([]);
  const [query, setQuery] = useState("");
  const [search, setSearch] = useState("");
  const APP_ID = "XXXXXXXXX";
  const APP_KEY = "XXXXXXXXXXXXXXXXXXXXXX";
  const url = `https://api.edamam.com/api/recipes/v2?type=public&q=${query}&app_id=${APP_ID}&app_key=${APP_KEY}`;

  const getRecipes = async () => {
    const res = await axios(url);
    const data = await res.data.hits;
    console.log(data);
    setRecipes(data);
  };
  useEffect(() => {
    getRecipes();
  }, [query]);

  const updateSearch = (e) => {
    setSearch(e.target.value);
    console.log(search);
  };

  const getSearchQuery = (e) => {
    e.preventDefault();
    setQuery(search);
    setSearch("");
    navigate("/recipes");
  };

  return (
    <div className="App">
      <Header />
      <div>
        <div className="container">
          <form className="search-form" onSubmit={getSearchQuery}>
            <input
              className="search-input"
              type="text"
              value={search}
              onChange={updateSearch}
              placeholder="search by food name"
            />
          </form>
        </div>
      </div>

        <Routes>
          <Route path="/recipes" element={<RecipeList recipes={recipes} />} />
          <Route path="/recipes/:id" element={<Recipe recipes={recipes} />}/>
        </Routes>
    
    </div>
  );
}

export default App;  

RecipeList.jsx

import React from "react";

import { Link } from "react-router-dom";

const RecipeList = ({ recipes }) => {
  return (
    <div className="container">
      <div className="grid-container">
        {recipes.map(({ recipe }) => (
          <Link to={`/recipes/${recipe.label}`}>
            <img key={recipe.image} src={recipe.image} alt="" />
            <p key={recipe.label}>{recipe.label}</p>
            <p>{recipe.id}</p>
          </Link>
        ))}
      </div>
    </div>
  );
};

export default RecipeList;

Recipe.jsx


const Recipe = ({recipe}) => {

    return (
        <div>
            <h1>{recipe.label}</h1>
        </div>
    )
}

export default Recipe

Am I even close???

CodePudding user response:

You are passing the entire recipes array to both routed components.

<Routes>
  <Route path="/recipes" element={<RecipeList recipes={recipes} />} />
  <Route path="/recipes/:id" element={<Recipe recipes={recipes} />}/>
</Routes>

So Recipe can use the entire array and the id route match param to search the passed array and render the exact recipe by matching label.

import { useParams } from 'react-router-dom';

const Recipe = ({ recipes }) => {
  const { id } = useParams();
  const recipe = recipes.find(recipe => recipe.label === id); // *

  return recipe ? (
    <div>
      <h1>{recipe.label}</h1>
    </div>
  ) : null;
};

* Note: Since you call the route param id it may make more sense to us the recipe.id for the link.

{recipes.map(({ recipe }) => (
  <Link to={`/recipes/${recipe.id}`}>
    <img key={recipe.image} src={recipe.image} alt="" />
    <p key={recipe.label}>{recipe.label}</p>
    <p>{recipe.id}</p>
  </Link>
))}

...

const recipe = recipes.find(recipe => recipe.id === id);
  • Related