-
Rust로 SPA 만들기 - 2. 카트에 물건 담기SPA 2021. 7. 4. 11:34
아래의 예제는 출처에 포함된 내용을 번역 한 것입니다.
이번에는 카트에 물건을 추가하는 기능을 만들어 보도록 하겠습니다.
- cart_products라는 새로운 상태 필드에서 장바구니에 추가 된 모든 제품을 추적합니다.
- 카트에 담기라는 버튼을 만들어서 각 product에 렌더링해주도록 하겠습니다.
- cart_products라는 버튼을 클릭하면 state로직을 업데이트 해주도록 하겠습니다.
home.rs 파일을 다음과 같이 수정합니다.
// src/pages/home.rs use yew::prelude::*; #[derive(Clone)] struct Product { id: i32, name: String, description: String, image: String, price: f64 } struct CartProduct { product: Product, quantity: i32 } struct State { products: Vec<Product>, cart_products: Vec<CartProduct> } pub struct Home { state: State, link: ComponentLink<Self>, } pub enum Msg { AddToCart(i32), } impl Component for Home { type Message = Msg; type Properties = (); fn create(_: Self::Properties, link: ComponentLink<Self>) -> Self { let products: Vec<Product> = vec![ Product { id: 1, name: "Yeongmin".to_string(), description: "Yegonmin is smilar to irang".to_string(), image: "/products/apple.png".to_string(), price: 3.65, }, Product { id: 2, name: "Irang".to_string(), description: "Irang is smilar to yeongmin".to_string(), image: "/products/banana.png".to_string(), price: 7.99, } ]; let cart_products = vec![]; Self { state: State { products, cart_products }, link, } } fn update(&mut self, message: Self::Message) -> ShouldRender { match message { Msg::AddToCart(product_id) => { let product = self .state .products .iter() .find(|p: &&Product| p.id == product_id) .unwrap(); let cart_product = self .state .cart_products .iter_mut() .find(|cp: &&mut CartProduct| cp.product.id == product_id); if let Some(cp) = cart_product { cp.quantity += 1; } else { self.state.cart_products.push(CartProduct { product: product.clone(), quantity: 1, }) } true } } } fn change(&mut self, _: Self::Properties) -> ShouldRender { true } fn view(&self) -> Html { let products: Vec<Html> = self .state .products .iter() .map(|product: &Product| { let product_id = product.id; html! { <div> <img src={&product.image} /> <div>{&product.name}</div> <div>{"$"}{&product.price}</div> <button onclick=self.link.callback(move |_| Msg::AddToCart(product_id))>{"카트에 담기"}</button> </div> } }) .collect(); let cart_value = self .state .cart_products .iter() .fold(0.0, |acc, cp| acc + (cp.quantity as f64 * cp.product.price)); html! { <div> <span>{format!("카트값: {:.2}", cart_value)}</span> <span>{products}</span> </div> } } }
- clone - 사용자가 장바구니에 추가할 때마다 복제된 제품을 CartProduct에 저장할 수 있록 Product struct에서 Clone 특성을 추출했습니다.
- update - 이 메서드는 컴포넌트의 상태를 업데이트하거나 request 요청과같은 부수작용을 담당하는 로직이 포함되어있습니다. 컴포넌트가 지원하는 모든 작업을 포함하는 enum을 사용하여 호출됩니다. 이 메서드가 true를 반환하면 컴포넌트가 다시 렌더링됩니다.
- link - 업데이트 생명주기 메서드를 트리거할 수 있는 콜백을 등록할 수 있습니다.
이 컴포넌트는 아래와 같이 동작합니다. 리덕스의 store에 디스패치하는 개념과 비슷하다고 보면 됩니다.
link는 dispatch와 유사하고 message는 액션과 유사합니다.
이제 빌드를 하고 다시 serve를 띄워서 카트에 담기 버튼을 클릭해보세요.
위와 같이 카트값이 잘 변하나요?
리액트나 여타 다른 자바스크립트 프레임워크와 달리 러스트로 웹어셈블리 코드에 접근하는 것은 조금 더 네이티브한 성능 이익을 볼 수 있습니다.
다음 시간에는 데이터를 직접 패치 데이터로 가져오는 것을 해보도록 하겠습니다.
감사합니다.
출처 : http://www.sheshbabu.com/posts/rust-wasm-yew-single-page-application/
'SPA' 카테고리의 다른 글
Rust로 SPA 만들기 - 1. 리스트 만들기 (0) 2021.07.03