Skip to content
This repository was archived by the owner on Mar 13, 2025. It is now read-only.

Commit d39e427

Browse files
grocery-list-manager #13
1 parent 583dced commit d39e427

File tree

1 file changed

+250
-0
lines changed

1 file changed

+250
-0
lines changed

grocery-list-react-web-app-project/README.md

Lines changed: 250 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,256 @@
44

55
This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
66

7+
## First Create React App by :
8+
```bash
9+
npx create-react-app grocery-list-organizer
10+
```
11+
## GroceryItem.js(GroceryItem component)
12+
Create an GroceryItem component that will be used for displaying the item. This will be a presentational component which takes the item as a prop and displays it.
13+
```bash
14+
import React from 'react';
15+
const Item = ({ item }) => {
16+
return (
17+
<div>
18+
<span>{item}</span>
19+
</div>
20+
);
21+
};
22+
export default Item;
23+
```
24+
25+
26+
27+
## GroceryItemList.js (GroceryItemList component)
28+
Now create a GroceryItemList component that will contain a list of all the items. This will take the items as a prop and display them as an ordered list. It will make use of the GroceryItem component that we just created for displaying individual elements.
29+
```bash
30+
import React from 'react';
31+
import Item from './Item';
32+
const ItemList = ({ items }) => {
33+
return (
34+
<div className="items-container">
35+
<ul>
36+
{items.map((item) => (
37+
<li>
38+
<Item key={item} item={item} />
39+
</li>
40+
))}
41+
</ul>
42+
</div>
43+
);
44+
};
45+
46+
export default ItemList;
47+
```
48+
49+
## App.js(App component)
50+
### Initial setup:
51+
Assume we have a list of items as an array. Later it will be dynamic, in the next section.
52+
```bash
53+
import React from 'react';
54+
import ItemList from './ItemList';
55+
const App = () => {
56+
const items = ["item 1", "item 2"]
57+
return (
58+
<div className="App">
59+
<header className="App-header">
60+
To Do items
61+
<ItemList items={items} />
62+
</header>
63+
</div>
64+
);
65+
}
66+
export default App;
67+
```
68+
Initial Setup is completed
69+
## React hook: useState
70+
The first hook that we will use is useState hook.Iit allows us to hook state into our functional component.
71+
As opposed to state in class components, useState does not work with object values. We can use primitives directly and create multiple react hooks for multiple variables if needed.
72+
```bash
73+
const [state, setState] = useState(initialState);
74+
```
75+
React hooks always need to be declared at the top of a function. This also helps preserve state in between all rendering that is happening for the component.
76+
Now replace the initialization of items to:
77+
```bash
78+
const [items, setItems] = useState(['item 1', 'item 2']);
79+
```
80+
81+
### Add a Grocery item functionality
82+
Now ,we have the items as a state variable, we can modify it in functions using the setter function. So, let us create the second section of the application which allows creating lists.
83+
We will create a different component for this. This component will have a form with an input field which will allow the user to enter the content of the new item that is to be added. It will also have a button which will add the item to the list..
84+
We also need a variable to store the item as the user types in the input text box. For this, we will create an item state which will be local to this component. And what better than using our new friend useState?
85+
The GroceryForm component will then look like:
86+
87+
```bash
88+
import React, { useState } from 'react';
89+
const GroceryForm = ({ addItem }) => {
90+
const [item, setItem] = useState(''); //or React.useState
91+
const handleSubmit = (e) => {
92+
e.preventDefault();
93+
addItem(item);
94+
setItem('');
95+
};
96+
return (
97+
<div>
98+
<p>Add item</p>
99+
<form onSubmit={handleSubmit}>
100+
<input value={item} onChange={(e) => setItem(e.target.value)} />
101+
<button>Add Item</button>
102+
</form>
103+
</div>
104+
);
105+
};
106+
export default GroceryForm;
107+
```
108+
Now that we have the functionality to add an item, we can modify our App component to declare the addItem function and also import the GroceryForm function that we just created.
109+
```bash
110+
const addItem = (item) => {
111+
// assuming no duplicates
112+
setItems([...items, item]);
113+
};
114+
```
115+
Finally,We destructured the existing items array, added the newly created item at the end of the array, and passed this new array to our setItems function that we learned about earlier.We can also remove the default values from the useState initialization since we have everything in place to add new items using the application now.
116+
## Deleting Item
117+
It is similar to adding item functionality, we will pass a remove item function from the parent component to the item list component which will be passed down to the item component. The item component will have a “clear” button whenever the user clicks it, the function will be invoke and item gets deleted.
118+
```bash
119+
import React from 'react';
120+
const Item = ({ item, removeItem }) => {
121+
return (
122+
<div>
123+
<span>{item}</span>
124+
<button onClick={() => removeItem(item)}>X</button>
125+
</div>);
126+
};
127+
```
128+
The GroceryItemList component have a similar change of taking the remove item prop in and passing it to the GroceryItem component.
129+
```bash
130+
import React from 'react';
131+
import GroceryItem from './GroceryItem';
132+
const ItemList = ({ items, removeItem }) => {
133+
return (
134+
<div className="grid-container ">
135+
<ol>
136+
{items.map((item) => (
137+
<li>
138+
<GroceryItem key={item} item={item} removeItem={removeItem} />
139+
</li>
140+
))}
141+
</ol>
142+
</div>
143+
);
144+
};
145+
export default ItemList;
146+
```
147+
148+
Then, we will define the remove item function in the parent component as:
149+
```bash
150+
const removeItem = (itemToBeDeleted) => {
151+
setItems(items.filter((item) => itemToBeDeleted !== item));
152+
};
153+
```
154+
## The React.useEffect hook
155+
By using this Hook, you tell React that your component needs to do something after render. React will remember the function you passed (we’ll refer to it as our “effect”), and call it later after performing the DOM updates. In this effect, we set the document title, but we could also perform data fetching or call some other imperative API. Placing useEffect inside the component lets us access the count state variable (or any props) right from the effect. We don’t need a special API to read it — it’s already in the function scope. Hooks embrace JavaScript closures and avoid introducing React-specific APIs where JavaScript already provides a solution.useEffect hook is somewhat similar to the life-cycle methods that we are aware of for class components. It runs after every render of the component including the initial render. Hence it can be thought of as a combination of componentDidMount, componentDidUpdate, and componentWillUnmount.If we want to control the behavior of when the effect should run (only on initial render, or only when a particular state variable changes), we can pass in dependencies to the effect to do so. This hook also provides a clean-up option to allow cleaning up of resources before the component is destroyed.
156+
basic syntax of the effect:
157+
158+
useEffect(didUpdate);
159+
160+
161+
162+
Here, didUpdate is a function that performs mutations, subscriptions, timers, logging, etc. It will get triggered after the component is rendered to the screen as well as on every subsequently completed render.Now,getting back to our Grocery application, let us put this in use to set the grocery item list data to local storage whenever we update the items in the grocery list. Add this following code in app component:
163+
```bash
164+
useEffect(() => {
165+
localStorage.setItem('items', JSON.stringify(items));
166+
});
167+
```
168+
This sets a key-value pair in local storage with the key being items and the value being a JSON representation of the Grocery items.
169+
Next, checking if there is any values in local storage.
170+
So the following piece of code:
171+
```bash
172+
const [items, setItems] = useState([]);
173+
transformed to:
174+
const saveditems = JSON.parse(localStorage.getItem('items'));
175+
const [items, setItems] = useState(saveditems || []);
176+
```
177+
Since loading from local storage is a synchronous process, code shoul work fine.
178+
```bash
179+
const [items, setItems] = useState([]);
180+
useEffect(() => {
181+
const items = JSON.parse(localStorage.getItem('items'));
182+
if (items) {
183+
setItems(items);
184+
}
185+
});
186+
```
187+
Above code dosent work because useEffect runs every time a component is rendered and we are calling set items inside the effect, it will trigger another render of the component, which triggers useEffect again. And the cycle goes on.
188+
189+
190+
## Firing useEffect
191+
The useEffect hook takes in a second argument which is an array of values that the effect depends on. This way, useEffect is only triggered again if one of these values changes.
192+
Calling useEffect only when necessary or when value changes.
193+
Using the dependency array, we can pass in the state variable to useEffect to make it fire useEffect only when the variable’s value changes.
194+
```bash
195+
useEffect(() => {
196+
const items = JSON.parse(localStorage.getItem('items'));
197+
if (items) {
198+
setItems(items);
199+
}
200+
}, [items]);
201+
```
202+
203+
### Calling useEffect only once on component
204+
Pass an empty array to useEffect as the second parameter to tell React to only run that effect only once.
205+
```bash
206+
useEffect(() => {
207+
const items = JSON.parse(localStorage.getItem('items'));
208+
if (items) {
209+
setItems(items);
210+
}
211+
}, []);
212+
213+
```
214+
Now that we know about the dependency array, it will be a good practice to add it to the effect that we were using to save the items to save to local storage as well.
215+
216+
```bash
217+
useEffect(() => {
218+
localStorage.setItem('items', JSON.stringify(items));
219+
}, [items]);
220+
```
221+
Finally , App component is ready:
222+
```bash
223+
import React, { useEffect, useState } from 'react';
224+
import AddItemForm from './AddItemForm';
225+
import './App.css';
226+
import ItemList from './ItemList';
227+
function App() {
228+
const [items, setItems] = useState([]);
229+
const addItem = (item) => {
230+
// assuming no duplicates for demo purposes
231+
setItems([...items, item]);
232+
};
233+
const removeItem = (itemToBeDeleted) => {
234+
setItems(items.filter((item) => itemToBeDeleted !== item));
235+
};
236+
useEffect(() => {
237+
const items = JSON.parse(localStorage.getItem('items'));
238+
if (items) {
239+
setItems(items);
240+
}
241+
}, []);
242+
useEffect(() => {
243+
localStorage.setItem('items', JSON.stringify(items));
244+
}, [items]);
245+
return (
246+
<div className="App">
247+
<header className="App-header">
248+
To Do items
249+
<ItemList items={items} removeItem={removeItem} />
250+
<AddItemForm addItem={addItem} />
251+
</header> </div>
252+
);}
253+
export default App;
254+
255+
```
256+
7257
## Available Scripts
8258
9259
In the project directory, you can run:

0 commit comments

Comments
 (0)