Search

State

State (μƒνƒœ)

μ»΄ν¬λ„ŒνŠΈκ°€ κ΄€λ¦¬ν•˜λŠ” 둜컬(λ‚΄λΆ€) 데이터
React μ»΄ν¬λ„ŒνŠΈμ˜ μƒνƒœ(State)λŠ” μ»΄ν¬λ„ŒνŠΈκ°€ κ΄€λ¦¬ν•˜λŠ” 둜컬 λ°μ΄ν„°μž…λ‹ˆλ‹€. μƒνƒœλ₯Ό μ‚¬μš©ν•˜λ©΄ μ»΄ν¬λ„ŒνŠΈκ°€ 동적인 데이터λ₯Ό μ €μž₯ν•˜κ³  ν‘œμ‹œν•  수 있으며, μƒνƒœκ°€ 변경될 λ•Œλ§ˆλ‹€ ReactλŠ” μžλ™μœΌλ‘œ 화면을 λ‹€μ‹œ λ Œλ”λ§ν•©λ‹ˆλ‹€.

State 의 νŠΉμ§•

1.
μƒνƒœ μ΄ˆκΈ°ν™” : μ»΄ν¬λ„ŒνŠΈκ°€ 생성될 λ•Œ useState ν›…μ΄λ‚˜ 클래슀 μ»΄ν¬λ„ŒνŠΈμ˜ constructor λ©”μ„œλ“œμ—μ„œ 초기 μƒνƒœλ₯Ό μ„€μ •ν•©λ‹ˆλ‹€.
2.
μƒνƒœ μ—…λ°μ΄νŠΈ : setCountλ‚˜ this.setStateλ₯Ό μ‚¬μš©ν•˜μ—¬ μƒνƒœλ₯Ό μ—…λ°μ΄νŠΈν•©λ‹ˆλ‹€. μ΄λ•Œ 이전 μƒνƒœλ₯Ό μ°Έμ‘°ν•˜μ—¬ 변경을 μ§„ν–‰ν•˜λŠ” 것이 μ€‘μš”ν•©λ‹ˆλ‹€.
3.
μ»΄ν¬λ„ŒνŠΈλ³„λ‘œ κ³ μœ ν•œ μƒνƒœ : 각각의 μΈμŠ€ν„΄μŠ€λŠ” 자체 μƒνƒœλ₯Ό μœ μ§€ν•˜λ―€λ‘œ, λ™μΌν•œ μ»΄ν¬λ„ŒνŠΈμ˜ μ—¬λŸ¬ μΈμŠ€ν„΄μŠ€ κ°„μ—λŠ” 각각 독립적인 μƒνƒœκ°€ μ‘΄μž¬ν•©λ‹ˆλ‹€.

μ‹€μŠ΅ μ½”λ“œ

β€œμƒν’ˆ 상세 UI λ§Œλ“€κΈ° - state”

β€œμƒν’ˆ 상세 UI λ§Œλ“€κΈ° - state” μ—μ„œλŠ” 1~3λ‹¨κ³„λ‘œ λ‚˜λˆ„μ–΄ μ‹€μŠ΅ν•©λ‹ˆλ‹€. 1단계 - JSX λ¬Έλ²•λ§Œμ„ μ‚¬μš©ν•˜μ—¬ ProductDetail.jsx μ»΄ν¬λ„ŒνŠΈλ₯Ό 정적 μ»¨ν…μΈ λ‘œ λ””μžμΈν•©λ‹ˆλ‹€. 2단계 - JavaScript 객체λ₯Ό μ‚¬μš©ν•˜μ—¬, λ™μ μœΌλ‘œ μƒν’ˆ 상세 정보λ₯Ό λžœλ”λ§ ν•©λ‹ˆλ‹€. 3단계 - quantity (μˆ˜λŸ‰) 을 μƒνƒœ(state) 둜 μ •μ˜ν•˜μ—¬, , λ²„νŠΌμ„ 눌러 이벀트 처리λ₯Ό ν•˜κ³ , μƒνƒœλ³€ν™”μ— 따라 λ¦¬λžœλ”λ§ν•˜λŠ” 과정을 ν™•μΈν•©λ‹ˆλ‹€.

μž‘μ—…ν•  파일

β€’
componets/ProductDetail.jsx
β€’
App.js
β€’
App.css

1단계

JSX λ¬Έλ²•λ§Œμ„ μ‚¬μš©ν•˜μ—¬ ProductDetail.jsx μ»΄ν¬λ„ŒνŠΈλ₯Ό 정적 μ»¨ν…μΈ λ‘œ λ””μžμΈν•©λ‹ˆλ‹€
β€’
componets/ProductDetail.jsx
β€’
App.js
β€’
App.css

μ»΄ν¬λ„ŒνŠΈ ꡬ쑰

β€’
App
β—¦
ProductDetail
App, ProductDetail μ»΄ν¬λ„ŒνŠΈ

componets/ProductDetail.jsx

import React from 'react' const ProductDetail = () => { return ( <div className='product-detail'> <div className="item img"> <img src="https://i.imgur.com/1vpSkbW.png" alt="μƒν’ˆλͺ…" /> </div> <div className="item info"> <div className="title"> <h1>μƒν’ˆλͺ…</h1> </div> <p> <span className='txt-pt'>INFO</span><br /> -νŽΈμ•ˆν•œ 착용이 κ°€λŠ₯ν•œ 폴라 λ””μžμΈ <br /> -μ²΄ν˜• 컀버가 κ°€λŠ₯ν•œ λ² μ΄μ§ν•œ 싀루엣 <br /> </p> <p> <span className="txt-pt">Color & Size</span> <br /> Black, Navy, Red <br /> 85, 90, 95, 100, 110 <br /> - μ–΄κΉ¨ 53, κ°€μŠ΄ 59, 암홀 23, μ†Œλ§€ 62, 총μž₯ 68 <br /> (μΈ‘μ • 방법에 따라 1~3cm μ˜€μ°¨κ°€ μžˆμ„ 수 μžˆμŠ΅λ‹ˆλ‹€) <br /> </p> <span className='line-lg'></span> <div className="text-group"> <div className="item"> <span className='txt-pt'>νŒλ§€κ°€</span> </div> <div className="item"> <span className='txt-pt'>42,000 원</span> </div> </div> <div className="text-group"> <div className="item"> <span>배솑비</span> </div> <div className="item"> <span>3,000</span> 원 </div> </div> <span className="line-lg"></span> <div className="text-group"> <div className="item"> <span>Color</span> </div> <div className="item"> <select name="color" id="color"> <option value="Black">Black</option> <option value="Navy">Navy</option> <option value="Red">Red</option> </select> </div> </div> <div className="text-group"> <div className="item"> <span>Size</span> </div> <div className="item"> <select name="color" id="color"> <option value="85">85</option> <option value="90">90</option> <option value="95">95</option> <option value="100">100</option> <option value="110">110</option> </select> </div> </div> <div className="text-group"> <div className="item"> <span>μˆ˜λŸ‰</span> </div> <div className="item flex"> <input type="text" className='quantity' min={1} max={100} value={1} /> <button className='btn btn-xs'>+</button> <button className='btn btn-xs'>-</button> </div> </div> <span className="line-lg"></span> <div className="text-group"> <div className="item"> <span className='txt-pt'>μ΅œμ’… 가격</span> </div> <div className="item"> <span className='txt-pt'>42,000</span> </div> </div> <div className="text-group flex gap-1"> <div className="item"> <button className="btn btn-lg">κ΅¬λ§€ν•˜κΈ°</button> </div> <div className="item flex"> <button className="btn btn-lg btn-outline">μž₯λ°”κ΅¬λ‹ˆ</button> <button className="btn btn-lg btn-outline">κ΄€μ‹¬μƒν’ˆ</button> </div> </div> </div> </div> ) } export default ProductDetail
JavaScript
볡사

App.js

import logo from './logo.svg'; import './App.css'; import ProductDetail from './components/ProductDetail'; function App() { return ( <div> <ProductDetail /> </div> ); } export default App;
JavaScript
볡사

App.css

.txt-pt { color: salmon; font-weight: bold; } .line-lg { display: block; border-bottom: 2px solid lightgray; } .product-detail { display: inline-flex; justify-content: center; column-gap: 100px; padding: 10px; /* border: 1px solid salmon; */ } .product-detail .item { width: 400px; } .product-detail .info { border-top: 2px solid black; border-bottom: 2px solid black; } .quantity { width: 40px; font-size: 16px; line-height: 20px; height: 20px; text-align: center; appearance: none; } /* 곡톡 */ .text-group { display: flex; padding: 10px 0; } img { width: 100%; } select { width: 100%; font-size: 16px; line-height: 40px; height: 40px; padding-left: 15px; padding-right: 15px; color: #222; color: inherit; cursor: pointer; outline: none; border: 1px solid #777; background: none; border-radius: 0; padding-right: 32px; } .flex { display: flex; } .flex.gap-1 { gap: 10px; } .btn { background-color: royalblue; color: white; font-weight: bold; outline: none; border: none; margin: 0 2px; padding: 0 10px; cursor: pointer; } .btn:hover { box-shadow: 2px 2px 2px rgba(0,0,0,0.5); } .btn:active { box-shadow: none; } .btn.btn-lg { width: 100%; min-height: 40px; } .btn.btn-outline { border: 2px solid gray; background-color: white; color: gray; }
CSS
볡사

2단계

JavaScript 객체λ₯Ό μ‚¬μš©ν•˜μ—¬, λ™μ μœΌλ‘œ μƒν’ˆ 상세 정보λ₯Ό λžœλ”λ§ ν•©λ‹ˆλ‹€.
β€’
componets/ProductDetail.jsx

μ»΄ν¬λ„ŒνŠΈ ꡬ쑰

β€’
App
β—¦
ProductDetail
App, ProductDetail μ»΄ν¬λ„ŒνŠΈ

componets/ProductDetail.jsx

import React, { useState } from 'react' const ProductDetail = (props) => { // βœ… 객체 μΆ”κ°€ const product = { productId : 'p000001', name : '베이직 폴라 λ‹ˆνŠΈ', price : 42000, quantity : 1, img: 'https://i.imgur.com/1vpSkbW.png', } // βœ… μ΅œμ’… 가격 계산 const totalPrice = product.price * product.quantity return ( <div className='product-detail'> <div className="item img"> <img src={product.img} alt={product.name} /> </div> <div className="item info"> <div className="title"> <h1>{product.name}</h1> </div> <p> <span className='txt-pt'>INFO</span><br /> -νŽΈμ•ˆν•œ 착용이 κ°€λŠ₯ν•œ 폴라 λ””μžμΈ <br /> -μ²΄ν˜• 컀버가 κ°€λŠ₯ν•œ λ² μ΄μ§ν•œ 싀루엣 <br /> </p> <p> <span className="txt-pt">Color & Size</span> <br /> Black, Navy, Red <br /> 85, 90, 95, 100, 110 <br /> - μ–΄κΉ¨ 53, κ°€μŠ΄ 59, 암홀 23, μ†Œλ§€ 62, 총μž₯ 68 <br /> (μΈ‘μ • 방법에 따라 1~3cm μ˜€μ°¨κ°€ μžˆμ„ 수 μžˆμŠ΅λ‹ˆλ‹€) <br /> </p> <span className='line-lg'></span> <div className="text-group"> <div className="item"> <span className='txt-pt'>νŒλ§€κ°€</span> </div> <div className="item"> <span className='txt-pt'>{product.price.toLocaleString()} 원</span> </div> </div> <div className="text-group"> <div className="item"> <span>배솑비</span> </div> <div className="item"> <span>3,000</span> 원 </div> </div> <span className="line-lg"></span> <div className="text-group"> <div className="item"> <span>Color</span> </div> <div className="item"> <select name="color" id="color"> <option value="Black">Black</option> <option value="Navy">Navy</option> <option value="Red">Red</option> </select> </div> </div> <div className="text-group"> <div className="item"> <span>Size</span> </div> <div className="item"> <select name="color" id="color"> <option value="85">85</option> <option value="90">90</option> <option value="95">95</option> <option value="100">100</option> <option value="110">110</option> </select> </div> </div> <div className="text-group"> <div className="item"> <span>μˆ˜λŸ‰</span> </div> <div className="item flex"> <input type="text" className='quantity' value={product.quantity} min={1} max={100} /> <button className='btn btn-xs'>+</button> <button className='btn btn-xs'>-</button> </div> </div> <span className="line-lg"></span> <div className="text-group"> <div className="item"> <span className='txt-pt'>μ΅œμ’… 가격</span> </div> <div className="item"> <span className='txt-pt'>{totalPrice.toLocaleString()} 원</span> </div> </div> <div className="text-group flex gap-1"> <div className="item"> <button className="btn btn-lg">κ΅¬λ§€ν•˜κΈ°</button> </div> <div className="item flex"> <button className="btn btn-lg btn-outline">μž₯λ°”κ΅¬λ‹ˆ</button> <button className="btn btn-lg btn-outline">κ΄€μ‹¬μƒν’ˆ</button> </div> </div> </div> </div> ) } export default ProductDetail
JavaScript
볡사

3단계

quantity (μˆ˜λŸ‰) 을 μƒνƒœ(state) 둜 μ •μ˜ν•˜μ—¬, , λ²„νŠΌμ„ 눌러 이벀트 처리λ₯Ό ν•˜κ³ , μƒνƒœλ³€ν™”μ— 따라 λ¦¬λžœλ”λ§ν•˜λŠ” 과정을 ν™•μΈν•©λ‹ˆλ‹€.
β€’
componets/ProductDetail.jsx

μ»΄ν¬λ„ŒνŠΈ ꡬ쑰

β€’
App
β—¦
ProductDetail
App, ProductDetail μ»΄ν¬λ„ŒνŠΈ

componets/ProductDetail.jsx

import React, { useState } from 'react' const ProductDetail = (props) => { // βœ… state μΆ”κ°€ const [quantity, setQuantity] = useState(1) // βœ… 객체 μΆ”κ°€ const product = { productId : 'p000001', name : '베이직 폴라 λ‹ˆνŠΈ', price : 42000, quantity : 1, img: 'https://i.imgur.com/1vpSkbW.png', } // βœ… μ΅œμ’… 가격 계산 const totalPrice = product.price * quantity // βœ… 이벀트 μ •μ˜ - 증가 const onIncrease = () => { console.log(quantity); setQuantity(quantity + 1) } // βœ… 이벀트 μ •μ˜ - κ°μ†Œ const onDecrease = () => { console.log(quantity); setQuantity(quantity - 1) } return ( <div className='product-detail'> <div className="item img"> <img src={product.img} alt={product.name} /> </div> <div className="item info"> <div className="title"> <h1>{product.name}</h1> </div> <p> <span className='txt-pt'>INFO</span><br /> -νŽΈμ•ˆν•œ 착용이 κ°€λŠ₯ν•œ 폴라 λ””μžμΈ <br /> -μ²΄ν˜• 컀버가 κ°€λŠ₯ν•œ λ² μ΄μ§ν•œ 싀루엣 <br /> </p> <p> <span className="txt-pt">Color & Size</span> <br /> Black, Navy, Red <br /> 85, 90, 95, 100, 110 <br /> - μ–΄κΉ¨ 53, κ°€μŠ΄ 59, 암홀 23, μ†Œλ§€ 62, 총μž₯ 68 <br /> (μΈ‘μ • 방법에 따라 1~3cm μ˜€μ°¨κ°€ μžˆμ„ 수 μžˆμŠ΅λ‹ˆλ‹€) <br /> </p> <span className='line-lg'></span> <div className="text-group"> <div className="item"> <span className='txt-pt'>νŒλ§€κ°€</span> </div> <div className="item"> <span className='txt-pt'>{product.price.toLocaleString()} 원</span> </div> </div> <div className="text-group"> <div className="item"> <span>배솑비</span> </div> <div className="item"> <span>3,000</span> 원 </div> </div> <span className="line-lg"></span> <div className="text-group"> <div className="item"> <span>Color</span> </div> <div className="item"> <select name="color" id="color"> <option value="Black">Black</option> <option value="Navy">Navy</option> <option value="Red">Red</option> </select> </div> </div> <div className="text-group"> <div className="item"> <span>Size</span> </div> <div className="item"> <select name="color" id="color"> <option value="85">85</option> <option value="90">90</option> <option value="95">95</option> <option value="100">100</option> <option value="110">110</option> </select> </div> </div> <div className="text-group"> <div className="item"> <span>μˆ˜λŸ‰</span> </div> <div className="item flex"> <input type="text" className='quantity' value={quantity} min={1} max={100} /> {/* value λ₯Ό state 둜 λ³€κ²½ */} <button className='btn btn-xs' onClick={ onIncrease }>+</button> {/* 이벀트 μΆ”κ°€ */} <button className='btn btn-xs' onClick={ onDecrease }>-</button> {/* 이벀트 μΆ”κ°€ */} </div> </div> <span className="line-lg"></span> <div className="text-group"> <div className="item"> <span className='txt-pt'>μ΅œμ’… 가격</span> </div> <div className="item"> <span className='txt-pt'>{totalPrice.toLocaleString()} 원</span> </div> </div> <div className="text-group flex gap-1"> <div className="item"> <button className="btn btn-lg">κ΅¬λ§€ν•˜κΈ°</button> </div> <div className="item flex"> <button className="btn btn-lg btn-outline">μž₯λ°”κ΅¬λ‹ˆ</button> <button className="btn btn-lg btn-outline">κ΄€μ‹¬μƒν’ˆ</button> </div> </div> </div> </div> ) } export default ProductDetail
JavaScript
볡사