๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
  • ์žฅ์›์ต ๊ธฐ์ˆ ๋ธ”๋กœ๊ทธ
๐Ÿ“บ Front End/- React, Next.js

[๋ฆฌ์•กํŠธ Hook] useState ๋กœ ์‚ฌ์šฉ์ž ์ž…๋ ฅ ๊ฐ’์„ ์ด์šฉํ•˜์—ฌ ๋ฐฐ์—ด ๋ Œ๋”๋ง ํ•˜๊ธฐ.

by Wonit 2020. 10. 16.

์ง€๋‚œ ์‹œ๊ฐ„ ์šฐ๋ฆฌ๋Š” useState๋ฅผ ์ด์šฉํ•˜์—ฌ ํ•จ์ˆ˜ํ˜• ์ปดํฌ๋„ŒํŠธ์— ์ƒํƒœ๋ฅผ ๋ถ€์—ฌํ•˜๊ธฐ์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณด์•˜๋‹ค.

 

ํ•˜์ง€๋งŒ ์ง€๋‚œ ์‹œ๊ฐ„ useState์— ๋Œ€ํ•ด์„œ ๋ง›๋งŒ ๋ดค๊ธฐ ๋•Œ๋ฌธ์— ์•„์ง ์‹ค์ „์—์„œ useState๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ์—๋Š” ํ„ฑ์—†์ด ๋ถ€์กฑํ•  ๊ฒƒ ๊ฐ™๋‹ค๋Š” ๋Š๋‚Œ์„ ๋ฐ›์•˜๋‹ค.

 

์˜ค๋Š˜์€ useState์— ๋Œ€ํ•ด์„œ ํ™•์‹คํžˆ ์ดํ•ดํ•ด๋ณด๊ณ  ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์„์ง€ ์•Œ์•„๋ณด๋Š” ์‹œ๊ฐ„์„ ๊ฐ€์ ธ๋ณด์ž.

์ตœ์ข… ๊ฒฐ๊ณผ๋ฌผ

์šฐ๋ฆฌ๊ฐ€ ์ด๋ฒˆ ์‹œ๊ฐ„ ์ตœ์ข…์ ์œผ๋กœ ๋งŒ๋“ค ๊ฒƒ์€ ์‚ฌ์šฉ์ž ์ž…๋ ฅ์— ๋”ฐ๋ผ์„œ ๋ฐฐ์—ด์„ ๋งŒ๋“ค๊ณ  ์ด๋ฅผ ์ถœ๋ ฅํ•˜๋Š” ํ™”๋ฉด์„ ๊ตฌ์„ฑํ•ด ๋ณผ ๊ฒƒ์ด๋‹ค.

 

๊ฒฐ๊ณผ๋ฌผ์€ ์•„๋งˆ ์ด๋ ‡๊ฒŒ ๋‚˜์˜ฌ๊ฒƒ์ด๋‹ค.

์ˆœ์„œ

  1. ์ž…๋ ฅ(input form) ํผ ์ƒ์„ฑ
  2. input ํผ์˜ onChange ๋ฉ”์„œ๋“œ ๊ตฌํ˜„
  3. useState๋ฅผ ์ด์šฉํ•˜์—ฌ state๋ฅผ ๋ณ€๊ฒฝ
  4. ์‚ฌ์šฉ์ž ์ถ”๊ฐ€ ๋ฒ„ํŠผ์˜ onClick ๋ฉ”์„œ๋“œ ๊ตฌํ˜„
  5. ๋ฐฐ์—ด ๋ Œ๋”๋ง

์ž…๋ ฅ ํผ ์ƒ์„ฑ (input form)

์šฐ์„  ์ž…๋ ฅ ํผ์„ ๋งŒ๋“ค์–ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์•„๋ž˜์™€ ๊ฐ™์ด ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด๋ณด์ž.

import React, { useState } from 'react';

const Test = () => {

  const [username, setUsername] = useState("")

  const [userAge, setUserAge] = useState("")

  return (
    <div>
      <h1>์‚ฌ์šฉ์ž๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”!</h1>
      <div>
        <input type="text" name="userName" />
        <input type="text" name="userAge" />
      </div>
    </div >
  );
}

export default Test;

์—ฌ๊ธฐ์„œ useState๊ฐ€ ์“ฐ์˜€๋‹ค.

 

์šฐ๋ฆฌ๋Š” <button>์œผ๋กœ input ํผ์— ์ž…๋ ฅ๋œ ๊ฐ’๋“ค์„ ๋ฐฐ์—ด์— ์ถ”๊ฐ€์‹œํ‚ฌ ๊ฒƒ์ด๋‹ˆ, input์— ์ž…๋ ฅ๋œ ๊ฐ’๋“ค์„ state๋กœ ๊ด€๋ฆฌํ•˜๋Š” ๊ฒƒ์ด ๋ฐ”๋žŒ์ง ํ•˜๋‹ค.

 

์—ฌ๊ธฐ์„œ username๊ณผ userAge๋Š” React์˜ Hook์œผ๋กœ ๊ตฌ์„ฑ๋˜์–ด ์žˆ๋‹ค.


๊ฐ๊ฐ์˜ state๋ฅผ ์ดˆ๊ธฐ ๋น„์–ด์žˆ๋Š” ๊ฐ’์œผ๋กœ ์ดˆ๊ธฐํ™”๋ฅผ ํ•ด์ค€๋‹ค.

input ํผ์˜ onChange ๋ฉ”์„œ๋“œ ๊ตฌํ˜„

์ด์ œ input ํผ๊ณผ state๋ฅผ ์—ฐ๊ฒฐ์‹œ์ผœ์•ผ ํ•œ๋‹ค๊ณ  ํ–ˆ์œผ๋‹ˆ, input์˜ onChange ๋ฉ”์„œ๋“œ๋ฅผ ๊ตฌํ˜„ํ•ด๋ณด์ž.

 

onChange ๋ฉ”์„œ๋“œ๋Š” ์‚ฌ์šฉ์ž์˜ ์ž…๋ ฅ์— ๋”ฐ๋ผ ๊ฐ๊ฐ์˜ state (username, userAge)๋ฅผ ๋ณ€ํ™”์‹œํ‚ค๋Š” ๊ฒƒ์ด๋‹ค.

 

๋‹ค์Œ๊ณผ ๊ฐ™์ด handleOnChange ๋ฉ”์„œ๋“œ๋ฅผ ์ž‘์„ฑํ•˜๊ณ  input ์†์„ฑ์˜ onChange ์†์„ฑ์— ๋„ฃ์–ด์ฃผ์ž.

import React, { useState } from 'react';


const Test = () => {

  const [username, setUsername] = useState("")

  const [userAge, setUserAge] = useState("")

  const handleOnChange = (e) => {
    console.log(e.target.name + ": " + "now changed");
  }

  return (
    <div>
      <h1>์‚ฌ์šฉ์ž๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”!</h1>
      <div>
        <input type="text" name="userName" onChange={handleOnChange} />
        <input type="text" name="userAge" onChange={handleOnChange} />
      </div>
    </div >
  );
}

export default Test;

๊ทธ๋ฆฌ๊ณ  input์— ๊ฐ’์„ ๋„ฃ์œผ๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ๋™์ž‘ํ•œ๋‹ค.

ํ•˜์ง€๋งŒ ์—ฌ๊ธฐ์„œ ์กฐ๊ธˆ ์ƒ์†Œํ•œ ๋ฌธ์žฅ์ด ๋‚˜ํƒ€๋‚ฌ๋‹ค.

const handleOnChange = (e) => {
  console.log(e.target.name + ": " + "now changed");
}

์—ฌ๊ธฐ ๋ณด๋ฉด handleOnChange ๋ฉ”์„œ๋“œ์˜ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ e๊ฐ€ ๋“ค์–ด๊ฐ€๊ณ  ์šฐ๋ฆฌ๋Š” ์ฝ˜์†”์— e.target.name์„ ์ถœ๋ ฅ์‹œ์ผฐ๋‹ค.

 

์—ฌ๊ธฐ์„œ ๋ง ํ•˜๋Š” e๋Š” ์ด๋ฒคํŠธ ์†์„ฑ์ธ๋ฐ, Event ์†์„ฑ์€ ๋งˆ์šฐ์Šค๋ฅผ ํด๋ฆญํ•˜๊ฑฐ๋‚˜ ํ‚ค๋ณด๋“œ๋ฅผ ๋ˆ„๋ฅด๋Š” ๋“ฑ ์‚ฌ์šฉ์ž ์•ก์…˜์— ์˜ํ•ด ๋ฐœ์ƒํ•˜๋Š” ์†์„ฑ์ด๋‹ค.

 

๊ทธ ์†์„ฑ์—๋Š” ์—ฌ๋Ÿฌ ๊ฐ’๋“ค์ด ๋‹ด๊ฒจ์žˆ๋Š”๋ฐ, ๊ทธ ์ค‘์—์„œ e.target์€ event๊ฐ€ ์ „๋‹ฌํ•œ ๊ฐ์ฒด์— ๋Œ€ํ•œ ์ฐธ์กฐ์ด๋‹ค.

 

์šฐ๋ฆฌ๋Š” event๊ฐ€ ์ „๋‹ฌํ•œ ๊ฐ์ฒด์˜ name์œผ๋กœ ์‹๋ณ„ํ•  ๊ฒƒ์ด๋ฏ€๋กœ e.target.name์ด๋ผ๊ณ  ์‹๋ณ„ํ•˜๋ฉด ์šฐ๋ฆฌ๊ฐ€ <input type="text" name="" />์œผ๋กœ ๋„ฃ์—ˆ๋˜ name ์†์„ฑ์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด๋‹ค.

 

์šฐ๋ฆฌ๊ฐ€ ์ž…๋ ฅํ•œ ๊ฐ’์€ input ํƒœ๊ทธ์˜ value๊ฐ’์œผ๋กœ ์ง€์ •๋˜๊ธฐ ๋•Œ๋ฌธ์— ์šฐ๋ฆฌ๋Š” e.target์— ์žˆ๋Š” value ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๊ณ  ํ•œ๋‹ค.

 

๊ทธ๋Ÿผ ์œ„์˜ handleOnChagne๋ฅผ ๋ณ€๊ฒฝํ•ด๋ณด์ž.

const handleOnChange = (e) => {
  console.log(e.target.name + ": " + e.target.value);
}

์ด์ œ ์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅํ•œ ๊ฐ’์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค!

useState๋ฅผ ์ด์šฉํ•˜์—ฌ state ๋ณ€๊ฒฝํ•˜๊ธฐ

๊ทธ๋Ÿผ ์•„๊นŒ ์šฐ๋ฆฌ๊ฐ€ onChange๋ฅผ ํ†ตํ•ด ์–ป๊ฒŒ๋œ ์‚ฌ์šฉ์ž์˜ ์ž…๋ ฅ ๊ฐ’์„ state๋กœ ์ €์žฅํ•ด๋ณด์ž.

 

์šฐ๋ฆฌ์—๊ฒ 2๊ฐœ์˜ state๊ฐ€ ์žˆ๋‹ค.

const [username, setUsername] = useState("")

const [userAge, setUserAge] = useState("")

์„๋จธ ๊ฐ๊ฐ์˜ state๋ฅผ ๋ณ€๊ฒฝ์‹œํ‚ค๊ธฐ ์œ„ํ•œ onChange ๋ฉ”์„œ๋“œ๊ฐ€ 2๊ฐœ๊ฐ€ ํ•„์š”ํ•˜๋‹ค.

const handleUserNameOnChange = (e) => {

}

const handleUserAgeOnChange = (e) => {

}

์—ฌ๊ธฐ์„œ ๊ฐ๊ฐ์˜ state๋ฅผ setState๋ฅผ ์ด์šฉํ•ด์„œ ๋ณ€๊ฒฝํ•˜๋ฉด ๋œ๋‹ค.

const handleUserNameOnChange = (e) => {
    setUsername(e.target.value)
}

const handleUserAgeOnChange = (e) => {
    setUserAge(e.target.value)
}

ํ•˜์ง€๋งŒ ๋งŒ์•ฝ ์ž…๋ ฅ ํผ์ด 100๊ฐœ๋ผ๋ฉด 100๊ฐœ์˜ handle ๋ฉ”์„œ๋“œ๋ฅผ ๋งŒ๋“ค์–ด์•ผ ํ• ๊นŒ??

 

๋„ˆ๋ฌด ๋ฉ‹์ง€์ง€ ์•Š๋‹ค.

 

๊ทธ๋ž˜์„œ ์šฐ๋ฆฌ๋Š” ํ•˜๋‚˜์˜ ๋ฐฉ๋ฒ•์„ ์ƒ๊ฐํ•ด ๋‚ผ ์ˆ˜ ์žˆ๋Š”๋ฐ, ์ž…๋ ฅ ํผ์„ ๊ฐ์ฒด๋กœ ๋งŒ๋“ค์–ด๋ฒ„๋ฆฌ๊ณ  target.name์œผ๋กœ ์‹๋ณ„ํ•˜๋ฉด ๋˜์ง€ ์•Š์„๊นŒ? ๋ผ๋Š” ์ƒ๊ฐ์„ ํ•  ์ˆ˜ ์žˆ๋‹ค.

const [inputs, setInputs] = useState({
  userName: "",
  userAge: ""
})

 

๋„ˆ๋ฌด ๋ฉ‹์ง„ ์ƒ๊ฐ์ธ ๊ฒƒ ๊ฐ™๋‹ค.

 

ํ•˜์ง€๋งŒ ๊ทธ ์ „์— ์•Œ์•„์•ผ ํ•  ๊ฒƒ์ด ์žˆ๋‹ค.

 

๋ฐ”๋กœ ์—ฌ๊ธฐ์„œ ES6 ๋ฌธ๋ฒ•์ด ์‚ฌ์šฉ๋œ๋‹ค.

 

ES6 ๋ฌธ๋ฒ•๊นŒ์ง€ ์ด์•ผ๊ธฐํ•˜์ž๋ฉด ๋„ˆ๋ฌด ์ปค์ง€๋ฏ€๋กœ ES6 ๋ฌธ๋ฒ•์€ ์—ฌ๊ธฐ์—์„œ ํ•™์Šตํ•˜๋Š” ๊ฒƒ์„ ์ถ”์ฒœํ•œ๋‹ค.

 

๊ทธ๋ž˜์„œ setInputs์—์„œ ๊ธฐ์กด์˜ input ๊ฐ’๋“ค์„ ๋ณต์‚ฌํ•ด์ฃผ๊ณ  ๋ณ€๊ฒฝ์ด ์ผ์–ด๋‚œ name์—์„œ value state๋ฅผ ๋ณ€๊ฒฝ์‹œ์ผœ์ฃผ๋ฉด ๋œ๋‹ค.

import React, { useState } from 'react';


const Test = () => {

  const [inputs, setInputs] = useState({
    userName: "",
    userAge: ""
  })

  const handleOnChange = (e) => {
    setInputs({
      ...inputs, 
      [e.target.name]: e.target.value
    })
  }

  return (
    <div>
      <h1>์‚ฌ์šฉ์ž๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”!</h1>
      <div>
        <input type="text" name="userName" onChange={handleOnChange} />
        <input type="text" name="userAge" onChange={handleOnChange} />
      </div>
    </div >
  );
}

export default Test;

์‚ฌ์šฉ์ž ์ถ”๊ฐ€ ๋ฒ„ํŠผ์˜ onCLick ๊ตฌํ˜„ํ•˜๊ธฐ

์ด์ œ input์„ ๋‹ค๋ค˜์œผ๋‹ˆ ์‚ฌ์šฉ์ž๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฒ„ํŠผ์˜ onClick์„ ๊ตฌํ˜„ํ•ด๋ณด์ž.

 

์ผ๋‹จ ์‚ฌ์šฉ์ž๊ฐ€ ์ €์žฅ๋  users state๋ฅผ ๋งŒ๋“ค์–ด๋ณด์ž.

 

๊ทธ๋ฆฌ๊ณ  onClick์ด ์‹คํ–‰๋˜๋ฉด ๊ธฐ์กด์— ์žˆ๋˜ ์ž…๋ ฅํผ์˜ ๊ฐ’๋“ค์€ ์ง€์›Œ์ ธ์•ผ ํ•˜๋ฏ€๋กœ Inputs๋ฅผ ๋น„์šฐ๋Š” ํ•จ์ˆ˜๋„ ๋„ฃ์„ ๊ฒƒ์ด๋‹ค.

const users = useState([]);

user state๋ฅผ ๋งŒ๋“ค๊ณ ,

const handleOnClick = () => {
const { userName, userAge } = inputs;

  // users ๋ฐฐ์—ด์— ์ถ”๊ฐ€ํ•  user ๊ฐ์ฒด
  const user = {
    userName,
    userAge
  }

  // spread ์—ฐ์‚ฐ์„ ํ†ตํ•ด์„œ ๊ธฐ์กด์˜ ๊ฐ’์„ ๋ณต์‚ฌํ•˜๊ณ , users State์— ์ถ”๊ฐ€
  setUsers([
    ...users,
    user
  ])

  // ์ž…๋ ฅ์ด ๋๋‚˜๊ณ  inputs๋ฅผ ๋น„์›Œ์ฃผ๋Š” ์—ญํ• 
   setInputs({
    userName: "",
    userAge: ""
  })
};

๋‹ค์Œ๊ณผ ๊ฐ™์€ onClick ๋ฉ”์„œ๋“œ๋ฅผ ๋งŒ๋“ค์ž.

 

์—ฌ๊ธฐ์„œ 3๊ฐ€์ง€๊ฐ€ ์‚ฌ์šฉ๋˜์—ˆ๋‹ค.

  1. user๊ฐ์ฒด
  2. spread ์—ฐ์‚ฐ์„ ํ†ตํ•œ users state ๋ณ€๊ฒฝ
  3. inputs ๋น„์›Œ์ฃผ๊ธฐ

์ด์ œ ๋งˆ์ง€๋ง‰์œผ๋กœ ๋ฐฐ์—ด ๋ Œ๋”๋ง์„ ํ†ตํ•œ ์ถœ๋ ฅ์„ ํ•ด๋ณด์ž.

๋ฐฐ์—ด ๋ Œ๋”๋ง

๋ฐฐ์—ด์„ ๋ Œ๋”๋งํ•˜๊ธฐ ์œ„ํ•ด ์ƒˆ๋กœ์šด ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งŒ๋“ ๋‹ค.

const User = ({ user }) => {
  return (
    <div>
      {user.userName} ({user.userAge})
    </div>
  );
}

์ด User ์ปดํฌ๋„ŒํŠธ๋Š” user๋ฅผ ํ”„๋กญ์Šค๋กœ ๋ฐ›์•„์™€์„œ ๋ Œ๋”๋ง ํ•ด์ค„ ๊ฒƒ์ด๋‹ค.

{users.map(user => (
    <User user={user} />
))}

๊ทธ๋Ÿผ ์šฐ๋ฆฌ๊ฐ€ ์•„๊นŒ ์›ํ•˜๊ณ ์ž ํ–ˆ๋˜ ๊ฒฐ๊ณผ๊ฐ€ ์ถœ๋ ฅ๋œ๋‹ค.


์‚ฌ์‹ค์ƒ ์ด๋ฒˆ ํฌ์ŠคํŒ…์—๋Š” ๋งŽ์€ ์˜ค๋ฅ˜๊ฐ€ ์žˆ๋‹ค.

 

๋ฐฐ์—ด ๋ Œ๋”๋ง์„ ์œ„ํ•œ key ๊ฐ’์„ ์ฃผ์ง€ ์•Š๋Š”๋‹ค๋˜๊ฐ€, ํ˜น์€ ๋„ˆ๋ฌด ๋งŽ์€ ๋ Œ๋”๋ง์œผ๋กœ ์„ฑ๋Šฅ ์ด์Šˆ๋ผ๋˜๊ฐ€

 

๋งŽ์€ ๋ถ€์กฑํ•œ ์ ์ด ์žˆ์ง€๋งŒ ์ด๋ฒˆ ๊ธ€์€ useState์— ์ดˆ์ ์„ ๋งž์ท„๊ธฐ ๋•Œ๋ฌธ์— ๊นŠ์€ ๋‚ด์šฉ์— ๋Œ€ํ•ด์„  ์ƒ๋žตํ–ˆ์Œ์„ ์•Œ๋ฆฐ๋‹ค.

๋Œ“๊ธ€