skip to Main Content

I am displaying the properties(recipe title, image url) of objects from a state. These objects are from mongodb. I have written below my current code flow.

  1. Create empty array state variable called initialRecipes via const [initialRecipes, setRecipes] = useState([]);
  2. Load the recipes from db and push each object to state array via setRecipes([...initialRecipes, response.data.message[i]])
  3. Render the recipes on the page via return() and loop through the initialRecipes variable via .map function
  4. Add new recipe to the state variable on form submission and show the newly added recipe automatically on the page – This is my current problem

Recipes.js

import React, { useState, useEffect } from 'react';
// code snippet

const Recipes = () => {
  const [formFieldValue, setFormFieldValues] = useState({
    recipe_name: '',
    image_url: '',
    buttonText: 'Submit'
  });
  const {recipe_name, image_url, buttonText} = formFieldValue;
  const [initialRecipes, setRecipes] = useState([]);

  useEffect(() => {
    loadAllRecipes();
  }, []);


  const loadAllRecipes = () => {
    axios({
      method: 'GET',
      url: `${process.env.REACT_APP_API}/recipe`,
    })
    .then(response => {
      for (let i=0; i<response.data.message.length; i++) {

        // save each object to state array
        setRecipes([
          ...initialRecipes,
          response.data.message[i]
        ])
      }
    })
    .catch(error => {
      // code snippet
    });
  };

  // save form input changes to state
  const handleChange = (name) => (event) => {
    setFormFieldValues({...formFieldValue, [name]: event.target.value});
  };


  // form fields snippet
  const addRecipeForm = () => (
    <form>
      <div className="form-group">
        <label className="text-muted">Recipe name</label>
        <input type="text" className="form-control recipe-form-input" value={recipe_name} onChange={handleChange('recipe_name')} />
      </div>

      <div className="form-group">
        <label className="text-muted">Image url</label>
        <input type="text" className="form-control recipe-form-input" value={image_url} onChange={handleChange('image_url')} />
      </div>

      <div>
        <button className="btn btn-primary btn-submit" onClick={handleSubmit}>Submit</button>
      </div>
    </form>
  );


  // add new recipe in the form
  const handleSubmit = event => {
    event.preventDefault();

    axios({
      method: 'POST',
      url: `${process.env.REACT_APP_API}/recipe`
    })
    .then(response => {
      console.log('Recipe is saved successfully!', response);
    })
    .catch(error => {
      // console.log(error.response.data.error);
    });
  };

  // show add recipe form and display all recipes using a loop
  return (
    <Layout>
      <div className="row">
        {addRecipeForm()}
      </div>

      <div className="row">
        <h2 className="title text-center">List of Recipes</h2>

        <div className="all-recipes-list ">
          {
            initialRecipes.map((recipe, index) => {
                return (
                  <div key={index} className="wrapper">
                    <img className="image" src={recipe.image_url} />
                    <a className="link" href="#">
                      <h4 className="title">{recipe.recipe_name}</h4>
                    </a>
                  </div>
                );
            })
          }
        </div>
    </Layout>
  );
};

export default Recipes;

Problem: How can I show the newly added Recipe via API(saved in MongoDB) endpoint in the <div className="all-recipes-list"></div> element of the page without page refresh?

Any help is greatly appreciated. Thanks!

2

Answers


  1. Chosen as BEST ANSWER

    I am able to solve this issue now. I just need to add setRecipes([...initialRecipes, newRecipe]); inside const handleSubmit = event => ();

      // add new recipe in the form
      const handleSubmit = event => {
        event.preventDefault();
    
        axios({
          method: 'POST',
          url: `${process.env.REACT_APP_API}/recipe`
        })
        .then(response => {
          let newRecipe = JSON.parse(response.config.data); // convert new recipe from string to object
          console.log('Recipe is saved successfully!', response);
    
          setRecipes([...initialRecipes, newRecipe]); // push new recipe to the state
        })
        .catch(error => {
          // console.log(error.response.data.error);
        });
      };
    

  2. After the post request, fetch the data using get request or simply use the react query to fetch data using the useQuery as it does what you want
    https://www.npmjs.com/package/react-query

    const handleSubmit = event => {
        event.preventDefault();
    
        axios({
          method: 'POST',
          url: `${process.env.REACT_APP_API}/recipe`
        })
        .then(response => {
          console.log('Recipe is saved successfully!', response);
          axios({
          method: 'GET',
          url: `${process.env.REACT_APP_API}/recipe`,
         })
         .then(response => {
           for (let i=0; i<response.data.message.length; i++) {
    
             // save each object to state array
             setRecipes([
               ...initialRecipes,
               response.data.message[i]
             ])
           }
         })
         .catch(error => {
           // code snippet
         });
        })
        .catch(error => {
          // console.log(error.response.data.error);
        });
      };
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search