diff --git a/June/article/4-useState-Mistakes-You-Should-Avoid-in-React.md b/June/article/4-useState-Mistakes-You-Should-Avoid-in-React.md new file mode 100644 index 0000000..b68e3d9 --- /dev/null +++ b/June/article/4-useState-Mistakes-You-Should-Avoid-in-React.md @@ -0,0 +1,252 @@ +## πŸ”— [4 useState Mistakes You Should Avoid in React🚫](https://medium.com/gitconnected/4-usestate-mistakes-you-should-avoid-in-react-0d9d676869e2) + +### πŸ—“οΈ λ²ˆμ—­ λ‚ μ§œ: 2024.06.10 + +### 🧚 λ²ˆμ—­ν•œ 크루: μ†Œν•˜(μ΅œμ†Œμ—°) + +--- + +## Reactμ—μ„œ ν”Όν•΄μ•Ό ν•  4가지 `useState` μ‹€μˆ˜πŸš« + +#### μ†Œκ°œ + +λ¦¬μ•‘νŠΈ(React.js)λŠ” μ»΄ν¬λ„ŒνŠΈ λ‚΄ μƒνƒœ 관리에 λŒ€ν•œ λ…νŠΉν•œ μ ‘κ·Ό λ°©μ‹μœΌλ‘œ ν˜„λŒ€ μ›Ή 개발의 μ΄ˆμ„μ΄ λ˜μ—ˆμŠ΅λ‹ˆλ‹€. 일반적인 ν›… 쀑 ν•˜λ‚˜μΈ useStateλŠ” κΈ°λ³Έμ μ΄μ§€λ§Œ μ’…μ’… 잘λͺ» μ‚¬μš©λ©λ‹ˆλ‹€. 효율적이고 버그 μ—†λŠ” μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ λ§Œλ“€κ³ μž ν•˜λŠ” μ΄ˆλ³΄μžμ™€ κ²½ν—˜μ΄ ν’λΆ€ν•œ 개발자 λͺ¨λ‘μ—κ²Œ μ΄λŸ¬ν•œ 일반적인 μ‹€μˆ˜λ₯Ό μ΄ν•΄ν•˜κ³  ν”Όν•˜λŠ” 것은 맀우 μ€‘μš”ν•©λ‹ˆλ‹€. + +이 λΈ”λ‘œκ·Έμ—μ„œλŠ” λ¦¬μ•‘νŠΈμ—μ„œ useStateλ₯Ό μ‚¬μš©ν•  λ•Œ ν”Όν•΄μ•Ό ν•  λ„€ 가지 μ€‘μš”ν•œ μ‹€μˆ˜λ₯Ό μžμ„Ένžˆ μ‚΄νŽ΄λ³΄κ² μŠ΅λ‹ˆλ‹€. ν•¨κ»˜ λ¦¬μ•‘νŠΈ κΈ°μˆ μ„ ν–₯μƒμ‹œμΌœ λ΄…μ‹œλ‹€! + +본격적으둜 μ‚΄νŽ΄λ³΄κΈ° 전에 [제 개인 μ›Ήμ‚¬μ΄νŠΈ](https://programwithjayanth.com/?source=post_page-----0d9d676869e2--------------------------------)μ—μ„œ μ›Ή κ°œλ°œμ— λŒ€ν•œ 보닀 심측적인 기사λ₯Ό μ‚΄νŽ΄λ³΄μ„Έμš”: + +#### μ‹€μˆ˜ 1: 이전 μƒνƒœλ₯Ό κ³ λ €ν•˜μ§€ μ•ŠμŒ 😨 + +React의 useState 훅을 μ‚¬μš©ν•  λ•Œ κ°€μž₯ 졜근의 μƒνƒœλ₯Ό μ—…λ°μ΄νŠΈν•  λ•Œ 이전 μƒνƒœλ₯Ό κ³ λ €ν•˜μ§€ μ•ŠλŠ” 것은 ν”ν•œ μ‹€μˆ˜μž…λ‹ˆλ‹€. μ΄λŸ¬ν•œ μ‹€μˆ˜λŠ” 특히 λΉ λ₯Έ λ˜λŠ” μ—¬λŸ¬ μƒνƒœ μ—…λ°μ΄νŠΈλ₯Ό μ²˜λ¦¬ν•  λ•Œ μ˜ˆμƒμΉ˜ λͺ»ν•œ λ™μž‘μ„ μ΄ˆλž˜ν•  수 μžˆμŠ΅λ‹ˆλ‹€. + +#### ❌ 문제 이해 + +Reactμ—μ„œ μΉ΄μš΄ν„°λ₯Ό λ§Œλ“ λ‹€κ³  κ°€μ •ν•΄ λ΄…μ‹œλ‹€. λ²„νŠΌμ„ 클릭할 λ•Œλ§ˆλ‹€ 카운트λ₯Ό μ¦κ°€μ‹œν‚€λŠ” 것이 λͺ©ν‘œμž…λ‹ˆλ‹€. κ°„λ‹¨ν•œ μ ‘κ·Ό 방법은 ν˜„μž¬ μƒνƒœ 값에 1을 λ”ν•˜λŠ” 것일 수 μžˆμŠ΅λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜ 이것은 λ¬Έμ œκ°€ 될 수 μžˆμŠ΅λ‹ˆλ‹€. + +```jsx +import React, { useState } from 'react'; + +const CounterComponent = () => { + const [counter, setCounter] = useState(0); + + const incrementCounter = () => { + setCounter(counter + 1); // 항상 μ˜ˆμƒλŒ€λ‘œ μž‘λ™ν•˜μ§€ μ•Šμ„ 수 μžˆμŠ΅λ‹ˆλ‹€. + }; + + return ( +
+

Counter: {counter}

+ +
+ ); +}; + +export default CounterComponent; +``` + +μœ„μ˜ μ½”λ“œμ—μ„œ incrementCounterλŠ” ν˜„μž¬ 값을 기반으둜 μΉ΄μš΄ν„°λ₯Ό μ—…λ°μ΄νŠΈν•©λ‹ˆλ‹€. 이것은 간단해 λ³΄μ΄μ§€λ§Œ 문제λ₯Ό μΌμœΌν‚¬ 수 μžˆμŠ΅λ‹ˆλ‹€. ReactλŠ” μ—¬λŸ¬ setCounter ν˜ΈμΆœμ„ ν•¨κ»˜ λ¬Άκ±°λ‚˜ λ‹€λ₯Έ μƒνƒœ μ—…λ°μ΄νŠΈκ°€ κ°„μ„­ν•˜μ—¬ μΉ΄μš΄ν„°κ°€ 맀번 μ˜¬λ°”λ₯΄κ²Œ μ—…λ°μ΄νŠΈλ˜μ§€ μ•Šμ„ 수 μžˆμŠ΅λ‹ˆλ‹€. + +#### βœ… μˆ˜μ •: + +μ΄λŸ¬ν•œ 문제λ₯Ό ν”Όν•˜κΈ° μœ„ν•΄ setCounter λ©”μ„œλ“œμ˜ ν•¨μˆ˜ν˜•μ„ μ‚¬μš©ν•˜μ„Έμš”. 이 버전은 Reactκ°€ κ°€μž₯ 졜근의 μƒνƒœ κ°’μœΌλ‘œ ν˜ΈμΆœν•˜λŠ” ν•¨μˆ˜λ₯Ό 인수둜 λ°›μŠ΅λ‹ˆλ‹€. μ΄λ ‡κ²Œ ν•˜λ©΄ 항상 μ΅œμ‹  μƒνƒœ κ°’μœΌλ‘œ μž‘μ—…ν•  수 μžˆμŠ΅λ‹ˆλ‹€. + +```jsx +import React, { useState } from 'react'; + +const CounterComponent = () => { + const [counter, setCounter] = useState(0); + + const incrementCounter = () => { + setCounter((prevCounter) => prevCounter + 1); // κ°€μž₯ 졜근의 μƒνƒœμ— 따라 μ˜¬λ°”λ₯΄κ²Œ μ—…λ°μ΄νŠΈλ©λ‹ˆλ‹€. + }; + + return ( +
+

Counter: {counter}

+ +
+ ); +}; + +export default CounterComponent; +``` + +μˆ˜μ •λœ μ½”λ“œμ—μ„œλŠ” incrementCounterκ°€ μƒνƒœλ₯Ό μ—…λ°μ΄νŠΈν•˜λŠ” 데 ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•©λ‹ˆλ‹€. 이 ν•¨μˆ˜λŠ” κ°€μž₯ 졜근의 μƒνƒœ(prevCounter)λ₯Ό λ°›μ•„ μ—…λ°μ΄νŠΈλœ μƒνƒœλ₯Ό λ°˜ν™˜ν•©λ‹ˆλ‹€. 이 μ ‘κ·Ό 방식은 특히 μ—…λ°μ΄νŠΈκ°€ λΉ λ₯΄κ²Œ μΌμ–΄λ‚˜κ±°λ‚˜ μ—°μ†μ μœΌλ‘œ μ—¬λŸ¬ 번 λ°œμƒν•  λ•Œ 훨씬 더 신뒰성이 λ†’μŠ΅λ‹ˆλ‹€. + +React JS μ‹€μ‹œκ°„ κ΅μœ‘μ— 관심이 μžˆλ‹€λ©΄ μžμ„Έν•œ λ‚΄μš©μ€ μ €μ—κ²Œ λ¬Έμ˜ν•΄ μ£Όμ„Έμš”. + +#### μ‹€μˆ˜ 2: μƒνƒœ λΆˆλ³€μ„± λ¬΄μ‹œ 🧊 + +#### ❌ 문제 이해 + +Reactμ—μ„œλŠ” μƒνƒœλ₯Ό λΆˆλ³€μœΌλ‘œ μ·¨κΈ‰ν•΄μ•Ό ν•©λ‹ˆλ‹€. ν”ν•œ μ‹€μˆ˜λŠ” 객체와 λ°°μ—΄κ³Ό 같은 λ³΅μž‘ν•œ 데이터 ꡬ쑰둜 μƒνƒœλ₯Ό 직접 μˆ˜μ •ν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€. + +μƒνƒœ 객체에 λŒ€ν•œ 잘λͺ»λœ μ ‘κ·Ό 방식을 κ³ λ €ν•΄ λ΄…μ‹œλ‹€: + +```jsx +import React, { useState } from 'react'; + +const ProfileComponent = () => { + const [profile, setProfile] = useState({ name: 'John', age: 30 }); + + const updateAge = () => { + profile.age = 31; // 직접 μƒνƒœ μˆ˜μ • + setProfile(profile); + }; + + return ( +
+

Name: {profile.name}

+

Age: {profile.age}

+ +
+ ); +}; + +export default ProfileComponent; +``` + +이 μ½”λ“œλŠ” profile 객체λ₯Ό 잘λͺ» μˆ˜μ •ν•©λ‹ˆλ‹€. μ΄λŸ¬ν•œ μˆ˜μ •μ€ μž¬λ Œλ”λ§μ„ νŠΈλ¦¬κ±°ν•˜μ§€ μ•ŠμœΌλ©° μ˜ˆμΈ‘ν•  수 μ—†λŠ” λ™μž‘μ„ μ΄ˆλž˜ν•©λ‹ˆλ‹€. + +#### βœ… μˆ˜μ •: + +μƒνƒœλ₯Ό μ—…λ°μ΄νŠΈν•  λ•ŒλŠ” 항상 λΆˆλ³€μ„±μ„ μœ μ§€ν•˜κΈ° μœ„ν•΄ μƒˆ 객체 λ˜λŠ” 배열을 μƒμ„±ν•˜μ„Έμš”. 이λ₯Ό μœ„ν•΄ μŠ€ν”„λ ˆλ“œ μ—°μ‚°μžλ₯Ό μ‚¬μš©ν•˜μ„Έμš”. + +```jsx +import React, { useState } from 'react'; + +const ProfileComponent = () => { + const [profile, setProfile] = useState({ name: 'John', age: 30 }); + + const updateAge = () => { + setProfile({ ...profile, age: 31 }); // μ˜¬λ°”λ₯΄κ²Œ μƒνƒœ μ—…λ°μ΄νŠΈ + }; + + return ( +
+

Name: {profile.name}

+

Age: {profile.age}

+ +
+ ); +}; + +export default ProfileComponent; +``` + +μˆ˜μ •λœ μ½”λ“œμ—μ„œ updateAgeλŠ” μƒνƒœ λΆˆλ³€μ„±μ„ μœ μ§€ν•˜λ©΄μ„œ μ—…λ°μ΄νŠΈλœ λ‚˜μ΄λ‘œ μƒˆ profile 객체λ₯Ό μƒμ„±ν•˜κΈ° μœ„ν•΄ μŠ€ν”„λ ˆλ“œ μ—°μ‚°μžλ₯Ό μ‚¬μš©ν•©λ‹ˆλ‹€. + +#### μ‹€μˆ˜ 3: 비동기 μ—…λ°μ΄νŠΈ 이해 λΆ€μ‘± ⏳ + +#### ❌ 문제 이해 + +useStateλ₯Ό ν†΅ν•œ React의 μƒνƒœ μ—…λ°μ΄νŠΈλŠ” λΉ„λ™κΈ°μ μž…λ‹ˆλ‹€. 특히 μ—¬λŸ¬ μƒνƒœ μ—…λ°μ΄νŠΈκ°€ λΉ λ₯Έ μ—°μ†μœΌλ‘œ μ΄λ£¨μ–΄μ§ˆ λ•Œ, μ΄λŠ” μ’…μ’… ν˜Όλž€μ„ μ΄ˆλž˜ν•©λ‹ˆλ‹€. κ°œλ°œμžλŠ” setState 호좜 직후 μƒνƒœκ°€ μ¦‰μ‹œ 변경될 κ²ƒμœΌλ‘œ μ˜ˆμƒν•  수 μžˆμ§€λ§Œ, μ‹€μ œλ‘œλŠ” Reactκ°€ μ„±λŠ₯μƒμ˜ 이유둜 μ΄λŸ¬ν•œ μ—…λ°μ΄νŠΈλ₯Ό 일괄 μ²˜λ¦¬ν•©λ‹ˆλ‹€. + +μ΄λŸ¬ν•œ μ˜€ν•΄κ°€ 문제λ₯Ό μΌμœΌν‚¬ 수 μžˆλŠ” 일반적인 μ‹œλ‚˜λ¦¬μ˜€λ₯Ό μ‚΄νŽ΄λ΄…μ‹œλ‹€. + +```jsx +import React, { useState } from 'react'; + +const AsyncCounterComponent = () => { + const [count, setCount] = useState(0); + + const incrementCount = () => { + setCount(count + 1); + setCount(count + 1); + // κ°œλ°œμžλŠ” countκ°€ 두 번 증가할 것을 μ˜ˆμƒ + }; + + return ( +
+

Count: {count}

+ +
+ ); +}; + +export default AsyncCounterComponent; +``` + +이 μ˜ˆμ œμ—μ„œ κ°œλ°œμžλŠ” countλ₯Ό 두 번 μ¦κ°€μ‹œν‚€λ €κ³  ν•©λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜ μƒνƒœ μ—…λ°μ΄νŠΈμ˜ 비동기적 νŠΉμ„±μœΌλ‘œ 인해 두 setCount ν˜ΈμΆœμ€ λͺ¨λ‘ λ™μΌν•œ 초기 μƒνƒœλ₯Ό 기반으둜 ν•˜λ―€λ‘œ countκ°€ ν•œ 번만 μ¦κ°€ν•©λ‹ˆλ‹€. + +#### βœ… μˆ˜μ •: + +비동기 μ—…λ°μ΄νŠΈλ₯Ό μ˜¬λ°”λ₯΄κ²Œ μ²˜λ¦¬ν•˜λ €λ©΄ setCount의 ν•¨μˆ˜ν˜• μ—…λ°μ΄νŠΈ ν˜•μ‹μ„ μ‚¬μš©ν•˜μ„Έμš”. μ΄λ ‡κ²Œ ν•˜λ©΄ 각 μ—…λ°μ΄νŠΈκ°€ κ°€μž₯ 졜근의 μƒνƒœλ₯Ό 기반으둜 μˆ˜ν–‰λ©λ‹ˆλ‹€. + +```jsx +import React, { useState } from 'react'; + +const AsyncCounterComponent = () => { + const [count, setCount] = useState(0); + + const incrementCount = () => { + setCount((prevCount) => prevCount + 1); + setCount((prevCount) => prevCount + 1); + // 이제 각 μ—…λ°μ΄νŠΈλŠ” κ°€μž₯ 졜근 μƒνƒœμ— μ˜¬λ°”λ₯΄κ²Œ 의쑴 + }; + // 선택사항: useEffectλ₯Ό μ‚¬μš©ν•˜μ—¬ μ—…λ°μ΄νŠΈ 된 μƒνƒœ 확인 + useEffect(() => { + console.log(count); // 2 + }, [count]); + + return ( +
+

Count: {count}

+ +
+ ); +}; + +export default AsyncCounterComponent; +``` + +μœ„μ˜ μ½”λ“œμ—μ„œ 각 setCount ν˜ΈμΆœμ€ μƒνƒœμ˜ κ°€μž₯ 졜근 값을 μ‚¬μš©ν•˜μ—¬ μ •ν™•ν•˜κ³  순차적인 μ—…λ°μ΄νŠΈλ₯Ό 보μž₯ν•©λ‹ˆλ‹€. 특히 μ—¬λŸ¬ μƒνƒœ μ—…λ°μ΄νŠΈκ°€ μ—°μ†μ μœΌλ‘œ λΉ λ₯΄κ²Œ λ°œμƒν•  λ•Œ ν˜„μž¬ μƒνƒœμ— μ˜μ‘΄ν•˜λŠ” μž‘μ—…μ—λŠ” 이 μ ‘κ·Ό 방식이 맀우 μ€‘μš”ν•©λ‹ˆλ‹€. + +#### μ‹€μˆ˜ 4: νŒŒμƒ 데이터에 λŒ€ν•œ μƒνƒœ 였용 πŸ“Š + +#### ❌ 문제 이해 + +κΈ°μ‘΄ μƒνƒœ λ˜λŠ” propsμ—μ„œ νŒŒμƒ 될 수 μžˆλŠ” 데이터에 μƒνƒœλ₯Ό μ‚¬μš©ν•˜λŠ” 것은 λΉˆλ²ˆν•œ 였λ₯˜μž…λ‹ˆλ‹€. 이 쀑볡 μƒνƒœλŠ” λ³΅μž‘ν•˜κ³  였λ₯˜κ°€ λ°œμƒν•˜κΈ° μ‰¬μš΄ μ½”λ“œλ₯Ό μ΄ˆλž˜ν•  수 μžˆμŠ΅λ‹ˆλ‹€. + +예λ₯Ό λ“€μ–΄: + +```jsx +import React, { useState } from 'react'; + +const GreetingComponent = ({ name }) => { + const [greeting, setGreeting] = useState(`Hello, ${name}`); + + return
{greeting}
; +}; + +export default GreetingComponent; +``` + +μ—¬κΈ°μ„œ greeting μƒνƒœλŠ” nameμ—μ„œ 직접 νŒŒμƒ 될 수 μžˆμœΌλ―€λ‘œ λΆˆν•„μš”ν•©λ‹ˆλ‹€. + +#### βœ… μˆ˜μ •: + +μƒνƒœλ₯Ό μ‚¬μš©ν•˜λŠ” λŒ€μ‹ , κΈ°μ‘΄ μƒνƒœ λ˜λŠ” propsμ—μ„œ 데이터λ₯Ό 직접 νŒŒμƒμ‹œν‚€μ„Έμš”. + +```jsx +import React from 'react'; + +const GreetingComponent = ({ name }) => { + const greeting = `Hello, ${name}`; // propsμ—μ„œ 직접 νŒŒμƒ + + return
{greeting}
; +}; + +export default GreetingComponent; +``` + +μˆ˜μ •λœ μ½”λ“œμ—μ„œλŠ” greeting은 name propμ—μ„œ 직접 κ³„μ‚°λ˜λ―€λ‘œ μ»΄ν¬λ„ŒνŠΈκ°€ λ‹¨μˆœν™”λ˜κ³  λΆˆν•„μš”ν•œ μƒνƒœ 관리λ₯Ό ν”Όν•  수 μžˆμŠ΅λ‹ˆλ‹€. + +#### κ²°λ‘  πŸš€ + +Reactμ—μ„œ useState 훅을 효과적으둜 μ‚¬μš©ν•˜λŠ” 것은 μ‹ λ’°μ„± 있고 효율적인 μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ κ΅¬μΆ•ν•˜λŠ” 데 맀우 μ€‘μš”ν•©λ‹ˆλ‹€. 이전 μƒνƒœ λ¬΄μ‹œ, μƒνƒœ λΆˆλ³€μ„± 관리 였λ₯˜, 비동기 μ—…λ°μ΄νŠΈ κ°„κ³Ό, νŒŒμƒ 데이터에 λŒ€ν•œ 쀑볡 μƒνƒœ 방지와 같은 일반적인 μ‹€μˆ˜λ₯Ό μ΄ν•΄ν•˜κ³  ν”Όν•¨μœΌλ‘œμ¨ 보닀 λ§€λ„λŸ½κ³  예츑 κ°€λŠ₯ν•œ μ»΄ν¬λ„ŒνŠΈ λ™μž‘μ„ 보μž₯ν•  수 μžˆμŠ΅λ‹ˆλ‹€. μ΄λŸ¬ν•œ μΈμ‚¬μ΄νŠΈλ₯Ό 염두에 두고 React 개발 여정을 ν–₯μƒμ‹œν‚€κ³  보닀 κ²¬κ³ ν•œ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ λ§Œλ“€μ–΄λ³΄μ„Έμš”. + +이 글이 λ§ˆμŒμ— λ“œμ…¨λ‚˜μš”? μ›Ή κ°œλ°œμ— λŒ€ν•œ 심측적인 ν† λ‘ κ³Ό μΈμ‚¬μ΄νŠΈλ₯Ό 보렀면 제 개인 λΈ”λ‘œκ·ΈμΈ Program With Jayanth λ₯Ό λ°©λ¬Έν•΄μ£Όμ„Έμš”. + +Happy Coding!!