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.
- Create empty array state variable called
initialRecipes
viaconst [initialRecipes, setRecipes] = useState([]);
- Load the recipes from db and push each object to state array via
setRecipes([...initialRecipes, response.data.message[i]])
- Render the recipes on the page via
return()
and loop through theinitialRecipes
variable via.map
function - 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
I am able to solve this issue now. I just need to add
setRecipes([...initialRecipes, newRecipe]);
insideconst handleSubmit = event => ();
After the post request, fetch the data using get request or simply use the
react query
to fetch data using theuseQuery
as it does what you wanthttps://www.npmjs.com/package/react-query