Home > Back-end >  Using the state function in another component
Using the state function in another component

Time:11-24

I am using useState to render the list of recipes based on the API call. i want to pass the setRecipeList function created in RecipeList component in the App.js component to render the list of recipes based on the response

RecipeList.js

    import React, { useState } from "react";
import Recipe from "./Recipe";
import styles from "./RecipeList.module.css";
const RecipeList = (props) => {
  const [recipeList, setRecipeList] = useState([]);
  setRecipeList();
  return (
    <div className={styles.recipe_list}>
      {recipeList.length &&
        recipeList.map((recipeObj) => (<Recipe recipeObj={recipeObj} />))}
    </div>
  );
};

export default RecipeList;

App.js

import React, { useState } from "react";
import Axios from "axios";
import Header from "./Components/Header";
import RecipeList from "./Components/RecipeList";

const APP_ID = "a6fee00c";
const APP_KEY = "a32eaaa328924a4d92edf81b006740e8";

function App() {
  const [timeoutId, setTimeoutId] = useState();

  const fetchRecipe = async (searchString) => {
    const response = await Axios.get(
      `https://api.edamam.com/search?q=${searchString}&app_id=${APP_ID}&app_key=${APP_KEY}`
    );
    console.log(response);
  };
  const onTextChangeHandler = (e) => {
    //debouncing - to skip API calls for initial letters when entering the input
    clearTimeout(timeoutId);
    const timeout = setTimeout(() => fetchRecipe(e.target.value), 500);
    setTimeoutId(timeout);
  };
  return (
    <>
    <Header onTextChange = {onTextChangeHandler} />
    <RecipeList/>
    </ >
  );
}

export default App;

link for the complete code - https://github.com/Moulya27/Recipe-Finder

CodePudding user response:

if you want a simple solution with useState, then I'd recommend to shift the useState to the App.js and pass the setRecipeList down into the RecipeList.js component.

RecipeList.js

...
const RecipeList = (props) => {
const { recipeList, setRecipeList } = props;

...


App.js

...
function App() {
  const [timeoutId, setTimeoutId] = useState();
  const [recipeList, setRecipeList] = useState([]);

  ...

 return (
   <>
     <Header onTextChange = {onTextChangeHandler} />
     <RecipeList recipeList={recipeList} setRecipeList={setRecipeList} />
   </ >
  );
}

export default App;

I didn't get much what you do with the setRecipeList in the recipe component but definitely it is good to wrap the fetch data into useEffectHook. Good luck!:)

CodePudding user response:

In order to pass data downstream, i.e. from App to RecipeList, you need to use props. Rather than declaring recipeList and setRecipeList in RecipeList, you could instead declare them in App, use setRecipeList inside fetchRecipe, and pass recipeList as a prop to RecipeList, where it can consume the data as it changes. Something like the following:

function App() {
  ...
  const [recipeList, setRecipeList] = useState([]);
  const fetchRecipe = async (searchString) => {
    const response = await Axios.get(
      `https://api.edamam.com/search?q=${searchString}&app_id=${APP_ID}&app_key=${APP_KEY}`
    );
    setRecipeList(response);
  };
  ...
  return (
    <>
      <Header onTextChange={onTextChangeHandler} />
      <RecipeList { ...recipeList } />
    </>
  );
}
const RecipeList = ({recipeList}) => {
  return (
    <div className={styles.recipe_list}>
      {recipeList.length &&
        recipeList.map((recipeObj) => (<Recipe recipeObj={recipeObj} />))}
    </div>
  );
};

Notice how I've used spread syntax to feed recipeList to RecipeList and destructuring assignment to pull recipeList directly out of RecipeList's props. I could also have said <RecipeList recipeList={recipeList} /> and (props) => ... props.recipeList ....

In general, the idiom in react is to create state at higher levels and pass either the state variable (recipeList), the setter function (setRecipeList), or both down to lower levels to suit your purpose. This can get unwieldy, however. Other options include useReducer and React Redux, which allow more fine-grained control.

Finally, as Yoshi also mentions, anything with timers should be dealt with using useEffect. Here's a previous answer of mine that demonstrates how and why.

  • Related