Unstated Next – ReactJS 的轻量级状态管理库 |部分 - 3 |购物车
在之前发表的文章中,我们使用 Unstated Next 实现了一个购物车。在本文中,我们将学习如何使用 Unstated Next 在React应用程序中处理多个组件的状态。
先决条件:
- 本文是上一篇的延续,请先参考。
- 并遵循前面文章的所有先决条件。
创建简单的购物车应用程序:
第 1 步:转到您 PC 上的首选位置并打开命令提示符并键入以下命令以创建一个新的 react 应用程序。
npx create-react-app shopping-cart
第 2 步:成功创建 React 应用程序后。使用以下命令进入其目录。
cd shopping-cart
第 3 步:创建 components 文件夹以添加新组件和 store 文件夹以使用 Unstated Next 库创建全局存储。按照以下命令创建文件夹。
mkdir src/components src/store
or
mkdir src\components src\store
第 4 步:安装一个名为 Unstated Next 的软件包:
npm i unstated-next
第 5 步:要验证一切是否正常,请运行以下命令来运行您的应用程序。
npm start
项目结构:在此之后,您的文件夹结构如下所示:
第 1 步:创建多个商店
在src/store文件夹中为购物车、用户和商品再创建 3 个商店。前面文章中给出的创建商店的详细说明参考了那个。
cart.js
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);
src/store/user.js
import { useState } from "react";
import { createContainer } from "unstated-next";
function useUser(initialState = []) {
// Storing users using array
let [users, setUser] = useState(initialState);
let addUser = (_user) => {
// Setting users list containing new user
setUser([...users, _user]);
};
let deleteUser = (_user) => {
// Filtering & deleting requested user
let newUser = users.filter((user) => user !== _user);
setUser(newUser);
};
return { users, addUser, deleteUser };
}
export default createContainer(useUser);
// returns {Procider , useContainer}
src/store/item.js
import { useState } from "react";
import { createContainer } from "unstated-next";
function useItem(initialState = []) {
// Storing items using array
let [items, setItem] = useState(initialState);
let addItem = (_item) => {
// Setting items list containing new item
setItem([...items, _item]);
};
let deleteItem = (_item) => {
// Filtering & deleting requested item
let newItem = items.filter((item) => item !== _item);
setItem(newItem);
};
return { items, addItem, deleteItem };
}
// Returns {Procider , useContainer}
export default createContainer(useItem);
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 (
Cart Items
{items.length > 0 ? (
items.map((item) => (
-
{item}{" "}
))
) : (
Cart is Empty
)}
setLocalItem(e.target.value)}
/>
{
addItem(localItem);
setLocalItem("");
}}
/>
);
}
export default Cart;
src/components/User.jsx
import React from "react";
function User() {
return (
User
);
}
export default User;
src/components/Item.jsx
import React from "react";
function Item() {
return (
Item
);
}
export default Item;
cart.css
.title {
font-family: Verdana, Geneva, Tahoma, sans-serif;
font-size: 3rem;
background-color: rgb(172, 172, 172);
margin: 10vh 30vw;
padding: 10px 22px;
width: 40vw;
border-radius: 5px;
}
.items {
padding: 22px;
width: 40vw;
border-radius: 5px;
margin: 10vh 30vw;
margin-top: -9vh;
background-color: rgb(221, 221, 171);
font-size: 1.5rem;
list-style-type: none;
}
.item-set {
display: flex;
justify-content: center;
align-items: center;
}
.item {
width: 10vw;
padding: 1vw;
}
.deleteButton {
width: 10vw;
height: 8vh;
font-size: 1.2rem;
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: 2vh 8vw;
outline: none;
border: none;
border-bottom: 2px solid rgb(172, 170, 170);
}
#submitButton {
padding: 10px 40px;
font-size: 1.2rem;
border-radius: 5px;
border: none;
background-color: rgb(100, 214, 167);
margin-left: 1vw;
}
#submitButton:active {
background-color: rgb(43, 129, 93);
color: wheat;
}
src/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 "childern"
const Provider = (props) => {
return (
// for cart
// for Item
// for user
{props.children}
);
};
export default Provider;
App.js
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 (
// it contains all 3 store providers
);
}
export default App;
src/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 (
{users.length > 0 &&
// Mapping through users array
users.map((user) => (
{user}
))}
setLocalUser(e.target.value)}
placeholder="user name"
>
// Adding new users
);
}
export default User;
src/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 (
{items.length > 0 &&
items.map((item) => (
{item}
))}
setLocalItem(e.target.value)}
placeholder="item name"
>
);
}
export default Item;
src/store/user.js
import { useState } from "react";
import { createContainer } from "unstated-next";
function useUser(initialState = []) {
// Storing users using array
let [users, setUser] = useState(initialState);
let addUser = (_user) => {
// Setting users list containing new user
setUser([...users, _user]);
};
let deleteUser = (_user) => {
// Filtering & deleting requested user
let newUser = users.filter((user) => user !== _user);
setUser(newUser);
};
return { users, addUser, deleteUser };
}
export default createContainer(useUser);
// returns {Procider , useContainer}
src/store/item.js
import { useState } from "react";
import { createContainer } from "unstated-next";
function useItem(initialState = []) {
// Storing items using array
let [items, setItem] = useState(initialState);
let addItem = (_item) => {
// Setting items list containing new item
setItem([...items, _item]);
};
let deleteItem = (_item) => {
// Filtering & deleting requested item
let newItem = items.filter((item) => item !== _item);
setItem(newItem);
};
return { items, addItem, deleteItem };
}
// Returns {Procider , useContainer}
export default createContainer(useItem);
第 2 步:创建多个组件
接下来,我们需要在src/components文件夹中为cart 、 users和items创建 3 个简单组件,并将其连接到App.js文件。
购物车.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 (
Cart Items
{items.length > 0 ? (
items.map((item) => (
-
{item}{" "}
))
) : (
Cart is Empty
)}
setLocalItem(e.target.value)}
/>
{
addItem(localItem);
setLocalItem("");
}}
/>
);
}
export default Cart;
src/components/User.jsx
import React from "react";
function User() {
return (
User
);
}
export default User;
src/components/Item.jsx
import React from "react";
function Item() {
return (
Item
);
}
export default Item;
购物车.css
.title {
font-family: Verdana, Geneva, Tahoma, sans-serif;
font-size: 3rem;
background-color: rgb(172, 172, 172);
margin: 10vh 30vw;
padding: 10px 22px;
width: 40vw;
border-radius: 5px;
}
.items {
padding: 22px;
width: 40vw;
border-radius: 5px;
margin: 10vh 30vw;
margin-top: -9vh;
background-color: rgb(221, 221, 171);
font-size: 1.5rem;
list-style-type: none;
}
.item-set {
display: flex;
justify-content: center;
align-items: center;
}
.item {
width: 10vw;
padding: 1vw;
}
.deleteButton {
width: 10vw;
height: 8vh;
font-size: 1.2rem;
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: 2vh 8vw;
outline: none;
border: none;
border-bottom: 2px solid rgb(172, 170, 170);
}
#submitButton {
padding: 10px 40px;
font-size: 1.2rem;
border-radius: 5px;
border: none;
background-color: rgb(100, 214, 167);
margin-left: 1vw;
}
#submitButton:active {
background-color: rgb(43, 129, 93);
color: wheat;
}
第 3 步:将 Providers 移动到 provider.js 文件:这一步非常重要,因为在之前的教程中,我们将 Provider 直接添加到了App.js文件中。因此,每次我们创建新商店时,我们都需要这样做。这使得App.js文件非常复杂,为避免这种情况,我们将所有提供程序添加到一个文件中,然后将其导入到App.js文件中。
为此,我们需要在src/store中创建一个provider.js文件,然后添加以下代码。
src/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 "childern"
const Provider = (props) => {
return (
// for cart
// for Item
// for user
{props.children}
);
};
export default Provider;
因此,每当您创建新商店时,您只需在此处添加即可。
现在我们需要将 Provider 导入App.js
应用程序.js
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 (
// it contains all 3 store providers
);
}
export default App;
第 4 步:在组件中使用 Store
我们需要将useContainer导入到各个组件中以使用商店数据。按照以下代码导入消费商店数据和方法。
- src/components/User.jsx:用这个替换之前的代码
src/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 (
{users.length > 0 &&
// Mapping through users array
users.map((user) => (
{user}
))}
setLocalUser(e.target.value)}
placeholder="user name"
>
// Adding new users
);
}
export default User;
src/components/Item.jsx:用这个替换之前的代码
src/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 (
{items.length > 0 &&
items.map((item) => (
{item}
))}
setLocalItem(e.target.value)}
placeholder="item name"
>
);
}
export default Item;
输出:
结论:我们通过创建一个单独的Provider.js文件成功地处理了多个商店。我希望您理解所有概念,以防您需要任何澄清,请随时在下面发表评论。