Unstated Next – Lightweight State Management Library For ReactJS | Part – 3 | Shopping Cart
We have implemented a shopping cart using Unstated Next In this article we are gonna learn how to handle states of more than one component in a React application using Unstated Next.
Prerequisites:
Steps to Create the React Application And Installing Module:
Step 1: Create a new react app.
npx create-react-app shopping-cart
Step 2: Go to its directory by using the below command.
cd shopping-cart
Step 3: Create components folder for adding new components and store folder for creating global store using Unstated Next library.
mkdir src/components src/store
or
mkdir src/components src/store
Step 4: Install a package called Unstated Next:
npm i unstated-next
Step 5: to verify everything is working or not, run the below command to run your application.
npm start
Project Structure:
The updated dependencies in package.json file will look like:
"dependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-scripts": "5.0.1",
"unstated-next": "^1.1.0",
"web-vitals": "^2.1.4",
}
Approach:
- Creating Multiple Store
- In the src/store folder create 3 more stores for cart, users, and items. detailed explanation for creating store given in the previous articles refer that.
- Creating Multiple Components
- Next, we need to create 3 simple components for cart, users, and items inside the src/components folder and connect that to the App.js file.
- Moving Providers to provider.js file:
- This Step is very important because in the previous tutorial we added Provider directly into the App.js file. so every time we create a new store we need to that. this makes the App.js file very complex, to avoid this we add all providers to a single file and then import that into the App.js file.
- For that, we need to create a provider.js file inside src/store and then add the below code.
Example: Below is the implementation of the above approach.
Javascript
import "./App.css" ; import Cart from "./components/Cart" ; import Item from "./components/Item" ; import User from "./components/User" ; import Provider from "./store/provider" ; function App() { return ( <div className= "App" > // it contains all 3 store providers <Provider> <Cart /> <User /> <Item /> </Provider> </div> ); } export default App; |
Javascript
//components/user.jsx import React, { useState } from "react" ; import useUser from "../store/user" ; function User() { // Extracting field and methods const { users, addUser } = useUser.useContainer(); // To capture user input const [localUser, setLocalUser] = useState( "" ); return ( <div style={{ padding: "2vw" , display: "flex" , justifyContent: "left" , width: "40vw" , margin: "auto" , }} > <div style={{ marginRight: "10px" , // Display items horizontally display: "flex" , }} > {users.length > 0 && // Mapping through users array users.map((user) => ( <p key={user} style={{ marginRight: 12 }}> {user} </p> ))} </div> <input type={ "text" } value={localUser} // Updating user input onChange={(e) => setLocalUser(e.target.value)} placeholder= "user name" ></input> // Adding new users <button onClick={() => addUser(localUser)}>Add</button> </div> ); } export default User; |
Javascript
//components/Item.jsx import React, { useState } from "react" ; import useItem from "../store/item" ; function Item() { const { items, addItem } = useItem.useContainer(); const [localItem, setLocalItem] = useState( "" ); return ( <div style={{ padding: "2vw" , display: "flex" , justifyContent: "left" , width: "40vw" , margin: "auto" , }} > <div style={{ marginRight: "10px" , display: "flex" , }} > {items.length > 0 && items.map((item) => ( <p key={item} style={{ marginRight: 12 }}> {item} </p> ))} </div> <input type={ "text" } value={localItem} onChange={(e) => setLocalItem(e.target.value)} placeholder= "item name" ></input> <button onClick={() => addItem(localItem)}> Add </button> </div> ); } export default Item; |
Javascript
store/provider.js import React from "react" ; import useUser from "./user" ; import useCart from "./cart" ; import useItem from "./item" ; // "props" will contain Child components // it named as "children" const Provider = (props) => { return ( <useCart.Provider> // for cart <useItem.Provider> // for Item // for user <useUser.Provider> {props.children} </useUser.Provider> </useItem.Provider> </useCart.Provider> ); }; export default Provider; |
Javascript
//cart.jsx import React, { useState } from "react" ; import "./cart.css" ; import useCart from "../store/cart" ; function Cart() { let { items, addItem, deleteItem } = useCart.useContainer(); const [localItem, setLocalItem] = useState( "" ); console.log(localItem, items); return ( <div> <h1 className= "title" >Cart Items</h1> <ol className= "items" > {items.length > 0 ? ( items.map((item) => ( <div className= "item-set" > <li className= "item" key={item}> {item}{ " " } </li> <button className= "deleteButton" onClick={() => deleteItem(item)}> Delete </button> </div> )) ) : ( <p>Cart is Empty</p> )} </ol> <input type= "text" id= "newItem" placeholder= "Item name" value={localItem} onChange={(e) => setLocalItem(e.target.value)} /> <input type= "button" id= "submitButton" value= "Add" onClick={() => { addItem(localItem); setLocalItem( "" ); }} /> </div> ); } export default Cart; |
Javascript
import { useState } from "react" ; import { createContainer } from "unstated-next" ; function useCart(initialState = []) { let [items, setItems] = useState(initialState); let addItem = (_item) => { setItems([...items, _item]); }; let deleteItem = (_item) => { let newItem = items.filter((item) => item !== _item); setItems(newItem); }; return { items, addItem, deleteItem }; } export default createContainer(useCart); |
CSS
/* Cart.css*/ .title { font-family : Verdana , Geneva, Tahoma , sans-serif ; font-size : 3 rem; background-color : rgb ( 172 , 172 , 172 ); margin : 10 vh 30 vw; padding : 10px 22px ; width : 40 vw; border-radius: 5px ; } .items { padding : 22px ; width : 40 vw; border-radius: 5px ; margin : 10 vh 30 vw; margin-top : -9 vh; background-color : rgb ( 221 , 221 , 171 ); font-size : 1.5 rem; list-style-type : none ; } .item-set { display : flex; justify- content : center ; align-items: center ; } .item { width : 10 vw; padding : 1 vw; } .deleteButton { width : 10 vw; height : 8 vh; font-size : 1.2 rem; border-radius: 5px ; border : none ; background-color : rgb ( 226 , 148 , 148 ); } .deleteButton:hover { background-color : rgb ( 211 , 101 , 101 ); color : rgb ( 255 , 253 , 253 ); } #newItem { padding : 2 vh 8 vw; outline : none ; border : none ; border-bottom : 2px solid rgb ( 172 , 170 , 170 ); } #submitButton { padding : 10px 40px ; font-size : 1.2 rem; border-radius: 5px ; border : none ; background-color : rgb ( 100 , 214 , 167 ); margin-left : 1 vw; } #submitButton:active { background-color : rgb ( 43 , 129 , 93 ); color : wheat; } |
Step to Run Application: Run the application using the following command from the root directory of the project.
npm start
Output:
Contact Us