IMPERATIVE ハンドルフックと NEXT JS CART 機能を使用する
8870 ワード
このチュートリアルでは、react の useImperativeHandle について学習し、このフックを使用して単純なカート機能を構築します.
を使用して反応プロジェクトを作成します
Component という名前のフォルダーを作成し、そのフォルダーに「Cart.tsx」というファイルを作成します.
上記のファイルでは、最初に、コンポーネントが期待する props とそのタイプを宣言するコンポーネントのインターフェイスを定義します.
コンポーネントを forwardRef でラップしていることに注意してください.これは、親コンポーネントから子コンポーネントに ref を渡すことができる別の反応フックです.これは、useImperativeHandle フックを機能させるために必要です.
次に、カートのデータを保存する状態を宣言します.
この実装のアイデアは、Cart.tsx コンポーネント内でカート データを保持する状態と、カート内の商品の追加、削除、および変更のための関数を宣言することです.しかし、このコンポーネントの外から addToCart 関数を呼び出したい (例えば、製品データが利用可能になる場所)、コンポーネントの外からこの関数だけを呼び出せるようにしたいので、それを useImperativeHandle 関数でラップします.
useImperativeHandle は、 forwardRef ハンドルを使用して親コンポーネントから渡される ref を受け取り、オブジェクトを返します (例: addToCart 関数).
addToCart 関数は、商品がすでにカートに入っているかどうかを確認し、そうでない場合はカートの状態に追加します.
他の関数は、カートからアイテムを削除し、カート内のアイテムの数を変更するために使用されます.
Components フォルダーに ProductComponent ファイルを作成します.
次のコードをファイルに貼り付けます
上記のファイルでは、ProductComponent プロパティのインターフェイスを宣言しており、これらのプロパティを使用してコンポーネントを作成しています.
次に、コンポーネント フォルダーに Results.tsx ファイルを作成します.
Results.tsx ファイルでは、Cart.tsx コンポーネントと product コンポーネントをインポートします.これは、useImperativeHandle フックをトリガーする場所です.
上記のファイルでは、「cartRef」という名前の ref を定義しています.これは、cart コンポーネントで useImperativeHandle をトリガーするために props として cart コンポーネントに渡される ref です.
このファイルで定義している addToCart 関数は、コンポーネントに渡す ref で現在のメソッドを呼び出すことにより、useImperativeHandle によって返される Cart コンポーネントの addToCart 関数をトリガーすることに注意してください.
ダミーデータを渡して ProductComponent を表示しましょう
設定
を使用して反応プロジェクトを作成します
create react app command
Component という名前のフォルダーを作成し、そのフォルダーに「Cart.tsx」というファイルを作成します.
import { FC, forwardRef, useImperativeHandle, useState } from "react";
interface ICartProps {
isOpen: boolean;
toggleCartOpen: () => void;
ref: any;
}
const Cart:FC<ICartProps> = forwardRef((props, cartRef: any) => {
const [cart, setCart] = useState([] as any[]);
useImperativeHandle(cartRef, () => ({
addToCart(product: any) {
let newCart = cart;
let obj = newCart.find((item: any, i: number) => {
if(item.name === product.name){
newCart[i] = product;
setCart(newCart);
return true;
}
})
if(!obj){
setCart(newCart.concat(product));
setTotalAmount(newCart.concat(product).reduce(
(acc: any, item: any) => acc + item.price * (item.quantity || 1),
0,
));
}
},
}));
const removeFromCart = (i: number) => {
let newCart = cart;
setCart(newCart.filter((item: any, index: number) => index !== i));
};
const changeProductQuantity = (i: number, quantity: number) => {
let newCart = cart;
newCart[i].quantity = quantity;
setCart(newCart);
}
return (
<div
className="flex flex-col justify-between w-20 h-10 fixed bottom-8 right-16"
>
<div>
{cart.map((item: any, i: any) => (
<div
className="flex flex-col w-[95%] py-1 border-b border-solid border-gray-800"
key={i}
>
<div className="flex flex-row justify-between">
<span
className="text-black text-base"
>
{item.name.toUpperCase()}
</span>
<button
className="py-1 px-2 text-center text-red-600 cursor-pointer"
onClick={() => removeFromCart(i)}
>
X
</button>
</div>
<div className="flex flex-row justify-between">
<p
className="text-gray-800 m-0"
>
N{item.price} x
</p>
<input
type="number"
className="w-[20%] py-1 px-2 text-center bg-gray-200 rounded-md"
defaultValue={item.quantity || 1}
onChange={(e: any) => onProductQuantityChange(i, e.target.value)}
/>
</div>
</div>
))}
</div>
</div>
)
});
export default Cart
上記のファイルでは、最初に、コンポーネントが期待する props とそのタイプを宣言するコンポーネントのインターフェイスを定義します.
コンポーネントを forwardRef でラップしていることに注意してください.これは、親コンポーネントから子コンポーネントに ref を渡すことができる別の反応フックです.これは、useImperativeHandle フックを機能させるために必要です.
次に、カートのデータを保存する状態を宣言します.
この実装のアイデアは、Cart.tsx コンポーネント内でカート データを保持する状態と、カート内の商品の追加、削除、および変更のための関数を宣言することです.しかし、このコンポーネントの外から addToCart 関数を呼び出したい (例えば、製品データが利用可能になる場所)、コンポーネントの外からこの関数だけを呼び出せるようにしたいので、それを useImperativeHandle 関数でラップします.
useImperativeHandle は、 forwardRef ハンドルを使用して親コンポーネントから渡される ref を受け取り、オブジェクトを返します (例: addToCart 関数).
addToCart 関数は、商品がすでにカートに入っているかどうかを確認し、そうでない場合はカートの状態に追加します.
他の関数は、カートからアイテムを削除し、カート内のアイテムの数を変更するために使用されます.
Components フォルダーに ProductComponent ファイルを作成します.
次のコードをファイルに貼り付けます
import Image from 'next/image
import { FC } from 'react'
import { HiShoppingCart } from 'react-icons/hi'
interface IProductComponentProps {
key: any;
result: any;
addToCart: (product: any) => void;
}
const ProductComponent: FC<IProductComponentProps> = (props) => {
return (
<div
className='flex flex-col bg-white rounded-md w-[70%] md:w-[90%] lg:w-[100%] mx-auto mb-8
p-4 lg:flex-row'
>
<Image
src="https://via.placeholder.com/100"
alt="product image"
width={100}
height={200}
className='rounded-md justify-center mr-4 h-auto cursor-pointer'
/>
<div
className="flex flex-col justify-between ml-3 pt-2"
>
<h3
className='text-lg font-mono'
>
{props.result.name}
</h3>
<p
className='text-gray-500 text-base line-clamp-2 mb-2'
>
{props.result.description}
</p>
<div
className='flex flex-row justify-between mb-2'
>
<p
className='text-base text-green-700 font-semibold'
>
{props.result.price }
</p>
</div>
<button
className="bg-orange-500 hover:bg-orange-700 text-white font-bold py-2 px-2 w-[50%]
flex justify-center mx-auto rounded-md"
onClick={() => props.addToCart(props.result)}
>
<HiShoppingCart className="text-lg text-center" />
</button>
</div>
</div>
)
}
export default ProductComponent
上記のファイルでは、ProductComponent プロパティのインターフェイスを宣言しており、これらのプロパティを使用してコンポーネントを作成しています.
次に、コンポーネント フォルダーに Results.tsx ファイルを作成します.
Results.tsx ファイルでは、Cart.tsx コンポーネントと product コンポーネントをインポートします.これは、useImperativeHandle フックをトリガーする場所です.
import { useRef, useState } from "react";
import Cart from "../Components/Cart";
const results = () => {
const cartRef = useRef({});
const addToCart = (newProduct:any) => {
cartRef.current?.addToCart(newProduct);
}
const [cartOpen, setCartOpen] = useState(false);
return (
<div>
<Cart
isOpen={cartOpen}
toggleCartOpen={openOrCloseCart}
ref={cartRef}
/>
</div>
}
上記のファイルでは、「cartRef」という名前の ref を定義しています.これは、cart コンポーネントで useImperativeHandle をトリガーするために props として cart コンポーネントに渡される ref です.
このファイルで定義している addToCart 関数は、コンポーネントに渡す ref で現在のメソッドを呼び出すことにより、useImperativeHandle によって返される Cart コンポーネントの addToCart 関数をトリガーすることに注意してください.
ダミーデータを渡して ProductComponent を表示しましょう
import { useRef, useState } from "react";
import Cart from "../Components/Cart";
const results = () => {
const cartRef = useRef({});
const addToCart = (newProduct:any) => {
cartRef.current?.addToCart(newProduct);
}
const [cartOpen, setCartOpen] = useState(false);
const products = [
{
name: 'SHIRT',
description: 'Product Description',
image: 'https://via.placeholder.com/100',
price: '$100',
discount_rate: '10%',
quantity: 2,
},
{
name: 'Attack on Titan',
description: 'Manga',
image: 'https://via.placeholder.com/100',
price: '$100',
discount_rate: '10%',
quantity : 2
},
{
name: 'Demon slayer ',
description: 'Manga',
image: 'https://via.placeholder.com/100',
price: '$100',
discount_rate: '10%',
quantity : 1
},
]
return (
<div>
<Cart
isOpen={cartOpen}
toggleCartOpen={openOrCloseCart}
ref={cartRef}
/>
{
products.map((product:any) => (
<ProductComponent
key={product.name}
result={product}
addToCart={addToCart}
/>
))
}
</div>
}
Reference
この問題について(IMPERATIVE ハンドルフックと NEXT JS CART 機能を使用する), 我々は、より多くの情報をここで見つけました https://dev.to/slickdev_raphael/useimperative-handle-hook-and-next-js-cart-functionality-5624テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol