[React] Movie-app Notes - State Practice

KAYAยท2021๋…„ 11์›” 8์ผ
0

[React] Movie-App

๋ชฉ๋ก ๋ณด๊ธฐ
4/11
post-thumbnail

๐Ÿ“’ Nomad Coder ReactJS๋กœ ์˜ํ™” ์›น ์„œ๋น„์Šค ๋งŒ๋“ค๊ธฐ
๊ฐ•์˜๋…ธํŠธ (2021 Updated ver.)


# 4. State Practice

Converter ๋งŒ๋“ค๊ธฐ

๋ถ„ -> ์‹œ๊ฐ„, ์‹œ๊ฐ„ -> ๋ถ„์œผ๋กœ ํ™˜์‚ฐํ•˜๋Š” ๋ณ€ํ™˜๊ธฐ๋ฅผ ๋งŒ๋“ค์–ด๋ณด์ž.

1. State ์ƒ์„ฑ

const [minutes, setMinutes] = React.useState();
const onChange = (e) => {
      setMinutes(e.target.value);
    }

minutes์—๋Š” ์•„๋ฌด ๊ฐ’๋„ ์„ ์–ธํ•˜์ง€ ์•Š์•˜๊ณ , onChangeํ•จ์ˆ˜๋ฅผ ์„ ์–ธํ•ด ์ด๋ฒคํŠธ ๋ฐœ์ƒ ์‹œ target(=input)์˜ ๊ฐ’์„ state์˜ ๊ฐ’์œผ๋กœ setํ•˜๋„๋ก ์„ค์ •ํ–ˆ๋‹ค.

2. return (UI)

<div>
  <h1 className="title">Converter</h1>
  <label htmlFor="min">Minutes </label>
  <input
        id="min"
	placeholder="Minutes"
	type="number"
	value={minutes} // state val === input val
	onChange={onChange} // onChange: ๋ณ€ํ™”๊ฐ€ ์žˆ์„ ๋•Œ๋งˆ๋‹ค ๊ฐ์ง€ํ•˜๋Š” func 
  />
  <h4>You are going to convert {minutes} to</h4>
  <label htmlFor="hrs">Hours </label>
  <input id="hrs" placeholder="Hours" type="number" />
</div>

๐Ÿ“Œ Check Point

JavaScipt๊ฐ€ ์„ ์ ํ•œ ๋‹จ์–ด๋ฅผ JSX์—์„œ ์“ฐ๋ฉด ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค. ๋‘˜์€ ์—„์—ฐํžˆ ๋‹ค๋ฅธ ์–ธ์–ด์ด๋‹ค.
JSX์—์„œ label์˜ ์†์„ฑ์œผ๋กœ for์„ ์“ฐ๋ฉด ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค. ์ด๋Š” JS ์–ธ์–ด์ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ class๋ฅผ ์“ฐ๋ฉด ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.
JSX์—์„œ ํ•ด๋‹น ์†์„ฑ์„ ๋ถ€์—ฌํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ์ ์šฉํ•ด์•ผ ํ•œ๋‹ค.

    <JS>       <JSX>  
    for   === HtmlFor
    class === ClassName

๊ฐ€์žฅ ์ฒ˜์Œ ์„ ์–ธํ•œ onChange()ํ•จ์ˆ˜๋ฅผ input์˜ onChange={}์†์„ฑ์— ๊ฑธ์–ด ์„ค์ •ํ•˜๋ฉด์„œ, input ๊ฐ’์— ๋ณ€ํ™”๊ฐ€ ์žˆ์„ ๋•Œ๋งˆ๋‹ค state ๊ฐ’(=minutes)๊ฐ€ ํ•ด๋‹น ๊ฐ’์œผ๋กœ ์—…๋ฐ์ดํŠธ๋˜๊ณ  ์ด ๊ฐ’์€ input value๋กœ ๋ณด์—ฌ์ง€๊ฒŒ ๋œ๋‹ค. (input val === state val)

ํ‚ค๋ณด๋“œ ์ž…๋ ฅ(์ด๋ฒคํŠธ ๋ฐœ์ƒ)
-> target(=input) value ๊ฐ์ง€
-> state ๊ฐ’์œผ๋กœ set
-> input value UI๋กœ ํ‘œ๊ธฐ

Final Code

์œ„ ์ฝ”๋“œ ํ”Œ๋กœ์šฐ๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ, ํ˜ธํ™˜์ด ๊ฐ€๋Šฅํ•œ Converter์„ ๊ตฌํ˜„ํ•œ๋‹ค.

1. ์‹œ๊ฐ„ -> ๋ถ„
2. ๋ถ„ -> ์‹œ๊ฐ„
<script type="text/babel">
  const root = document.getElementById("root")
  function App() {
    // create State
    const [amount, setAmount] = React.useState(0);
    const [flip, setFlip] = React.useState(false);
    const onChange = (e) => {
      // console.log(e.target.value);
      setAmount(e.target.value);
    }
    const reset = () => setAmount(0);
    const onflip = () => {
      reset();
      setFlip(current => !current);
      console.log(flip);
    } // ํ˜„์žฌ flip๊ฐ’์˜ ๋ฐ˜๋Œ€ 
    return (
      (
        <div>
          <h1 className="title">Converter</h1>
          <div>
            <label htmlFor="min">Minutes </label>
            <input
              id="min"
              placeholder="Minutes"
              type="number"
              value={flip ? amount * 60 : amount}
              // state val === input val
              onChange={onChange}  // onChange: ๋ณ€ํ™”๊ฐ€ ์žˆ์„ ๋•Œ๋งˆ๋‹ค ๊ฐ์ง€ํ•˜๋Š” func 
              disabled={flip} // == disabled={flip === true}
            // flip์ผ ๋•Œ disabled๋˜๋‹ˆ๊นŒ flip์ด๋ฉด ์‹œ๊ฐ„์ž…๋ ฅ๊ฐ€๋Šฅ 
            // ==> flip์ผ๋•Œ๋Š” ์‹œ๊ฐ„๊ฐ’*60์œผ๋กœ min ์ธํ’‹์ฐฝ์— ๋ณด์—ฌ์ ธ์•ผํ•จ.
            // ==> ์•„๋‹ˆ๋ผ๋ฉด amount ๊ทธ๋Œ€๋กœ ๋ณด์—ฌ์ ธ์•ผํ•จ
            />
          </div>
          <div>
            <label htmlFor="hrs">Hours </label>
            <input
              id="hrs"
              placeholder="Hours"
              type="number"
              value={flip ? amount : Math.round(amount / 60)}
              onChange={onChange}
              disabled={!flip} // == disabled={flip === false}
            // flip์ด false์ด๋ฉด ์ž…๋ ฅ๋ถˆ๊ฐ€๋Šฅ
            // flip์ด true์ผ ๊ฒฝ์šฐ, ์ž…๋ ฅ๊ฐ’ ๊ทธ๋Œ€๋กœ ํ‘œ๊ธฐ,
            // ์•„๋‹ˆ๋ผ๋ฉด 60์œผ๋กœ ๋‚˜๋ˆ„์–ด ํ‘œ๊ธฐ

            />
          </div>
          <button onClick={reset}>Reset</button>
          <button onClick={onflip}>{flip ? '->Change to *Mins to Hrs*' : '->Change to *Hrs to Mins*'}</button>
        </div>
      )
    )
  }
  ReactDOM.render(<App />, root);
</script>

๐Ÿ“Œ Check Point

  1. if๋ฌธ ํ•จ์ˆ˜๋กœ ํ‘œํ˜„ํ•˜๋Š” ๋Œ€์‹  ์‚ผํ•ญ์—ฐ์‚ฐ์ž๋กœ ๊ฐ„๋‹จํ•œ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๊ตฌํ˜„
  2. contents๋ฅผ state๋กœ ํ‘œํ˜„ (ex. button ๋‚ด์šฉ ๋ณ€๊ฒฝ)

Super Converter ๋งŒ๋“ค๊ธฐ

select, option๋กœ ์„ ํƒ์‚ฌํ•ญ์„ ์ถ”๊ฐ€ํ•ด๋ณด์ž.

function MinsToHrs() {...}
function KmToMile() {...}
function App() {
    const [index, setIndex] = React.useState('0');
    const onSelect = (e) => setIndex(e.target.value);
    return (
      (
        <div>
          <h1 className="title">Super Converter</h1>
          <select value={index} onChange={onSelect}>
            <option value="0">Minutes / Hours</option>
            <option value="1">km / Mile</option>
          </select>
          {index === '0' ? <MinsToHrs /> : null}
          {index === '1' ? <KmToMile /> : null}
        </div>
      )
    )
  }

๐Ÿ“Œ Check Point

  1. state๋ฅผ ๋ฐ”๊พธ๋ฉด ํ•ด๋‹น ์ปดํฌ๋„ŒํŠธ - ์—ฐ๊ณ„ ์ปดํฌ๋„ŒํŠธ๋Š” re-rendering ๋œ๋‹ค. ๋ฌด์กฐ๊ฑด!
  2. ์†์„ฑ์œผ๋กœ value ๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์œผ๋ฉดonChange ์†์„ฑ์„ ๋ถ™์ผ ์ˆ˜ ์žˆ๋‹ค.
  3. ์†์„ฑ๊ฐ’์„ ์ปจํŠธ๋กคํ•ด์„œ ๋กœ์ง์„ ๋งŒ๋“œ๋Š” ์—ฐ์Šต์„ ํ•˜์ž.

๋ง๋ถ™์ด๋Š” Code

์œ„์˜ ์ฝ”๋“œ๋ฅผ ์ฐธ๊ณ ํ•˜์—ฌ KM -> MILE Converter๋ฅผ ๋งŒ๋“ค์—ˆ๋‹ค.

function KmToMile() {
    const [amount, setAmount] = React.useState(1);
    const [km, setKm] = React.useState(true);
    const onChange = (e) => {
      setAmount(e.target.value)
    };
    const reset = () => setAmount('');
    const onKm = () => {
      reset();
      setKm(cur => !cur) // ์ด๊ฒŒ ๋ฐ”๋€Œ๋ฉด disabled์— ์˜ํ–ฅ์„ ์ฃผ๋‹ˆ๊นŒ.
    }
    return (
      <div>
        <h3>KM to MILE</h3>
        <div>
          <label htmlFor="km">Km </label>
          <input
            type="number"
            id="km"
            value={km ? amount : (amount / 1.609).toFixed(2)}
            onChange={onChange}
            disabled={!km}
          />
        </div>

        <div>
          <label htmlFor="mile">Mile </label>
          <input
            type="number"
            id="mile"
            value={km ? (amount * 1.609).toFixed(2) : amount}
            onChange={onChange}
            disabled={km}
          />
        </div>
        <div>
          <button onClick={onKm}>{km ? 'Change Mile converter' : 'Change Km Converter'}</button>
        </div>
        <div>
          <button onClick={reset}>reset</button>
        </div>
      </div>
    )

Flow

km๊ฐ’์„ ์‹œ์ž‘์œผ๋กœ, km ๋ชจ๋“œ์ด๋ฉด mile์ด disabled
-> km value ์ž…๋ ฅ
-> target value๋กœ amount state ๋ณ€๊ฒฝ
-> km ๋ชจ๋“œ์ด๋ฏ€๋กœ km์นธ amount ๊ทธ๋Œ€๋กœ ํ‘œ๊ธฐ,
mile์นธ *1.609, ์†Œ์ˆ˜์  2์ž๋ฆฌ๊นŒ์ง€ ํ‘œ๊ธฐ(.toFixed())

-> mode change
-> onKm()๋ฐœ๋™
-> ์ž…๋ ฅ๊ฐ’ / ๊ณ„์‚ฐ๊ฐ’ ๋ฆฌ์…‹,
km ํ˜„์žฌ ๊ฐ’์ด true ์˜€์œผ๋ฏ€๋กœ false๋กœ ๋ณ€ํ™˜
-> km === false์ด๋ฏ€๋กœ km์นธ disabled, mile์นธ abled
-> mile converter ์‚ฌ์šฉ๊ฐ€๋Šฅ


Overall Summary

์ด ์ผ๋ จ์˜ ๊ณผ์ •์œผ๋กœ ๋กœ์ง์„ ๊ฐ–๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ถ„๋ฆฌํ•ด ์ƒ์„ฑํ•˜๋Š” ์—ฐ์Šต์„ ํ–ˆ๋‹ค.

* ์ปดํฌ๋„ŒํŠธ  :  App(), MinsToHrs(), KmToMile()

๊ฐ ๋กœ์ง์— ๋”ฐ๋ผ ์ปดํฌ๋„ŒํŠธ๋กœ ๋…๋ฆฝ๊ฐœ์ฒด๋กœ ๋ถ„ํ• ํ•˜๋ฉด ์‚ฌ์šฉ์„ฑ๊ณผ ํšจ์œจ์ด ์ƒ์Šนํ•˜๊ณ , ํ•„์š”์— ๋”ฐ๋ผ ์žฌ์‚ฌ์šฉ๋„ ๊ฐ€๋Šฅํ•˜๋‹ค. ์‰ฝ๊ฒŒ ๋งํ•ด ์š”์†Œ๋ฅผ ์ปจํŠธ๋กคํ•˜๊ธฐ ์‰ฌ์›Œ์ง„๋‹ค.

 ๋ถ„ํ•  => ์ •๋ณต

์—ฌ๊ธฐ์„œ ์ƒ๊ฐํ•ด ๋ณผ ๋ฌธ์ œ

๋ชจ๋“  ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ฐฉ๊ธˆ ๊ตฌํ˜„ํ•œ ๊ฒƒ์ฒ˜๋Ÿผ ํ•œ ํŽ˜์ด์ง€์— ๋ชฐ๋ ค์žˆ๋‹ค๋ฉด?
๋‚˜์ค‘์— ์•ฑ์ด ๊ณ ๋„๋กœ ๋ฐœ์ „ํ•ด 1์–ต๊ฐœ์˜ ๋‹จ์œ„ํ™˜์‚ฐ์ด ํ•„์š”ํ•˜๊ฒŒ ๋œ๋‹ค๋ฉด, ์šฐ๋ฆฌ๋Š” 1์–ต๊ฐœ์˜ ์ปดํฌ๋„ŒํŠธ๋ฅผ ํ•œ ํŽ˜์ด์ง€์—์„œ ๊ด€๋ฆฌํ•ด์•ผ ํ•œ๋‹ค. ์ด๊ฒƒ์€ ๋งค์šฐ ๋น„ํšจ์œจ์ ์ด๋‹ค.

์ปดํฌ๋„ŒํŠธ๋Š” ๊ฐ๊ฐ ๋กœ์ง์— ๋”ฐ๋ผ ๋ถ„๋ฅ˜๋˜์–ด์ ธ์•ผ ํ•  ๊ฒƒ์ด๊ณ , ๋ถ„๋ฆฌ๋œ ์ปดํฌ๋„ŒํŠธ๋“ค์„ ์ž˜ ์—ฐ๊ฒฐํ•ด ๋ฐ์ดํ„ฐ ์ „๋‹ฌ์ด ์šฉ์ดํ•˜๋„๋ก ๋งŒ๋“ค์–ด์•ผ ์˜ค๋ฅ˜์—†๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ์ด๋‹ค.
๋…๋ฆฝ์ ์œผ๋กœ ๋ถ„๋ฅ˜๋œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋” ํšจ์œจ์ ์œผ๋กœ ๊ด€๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ํ•„์š”ํ•œ ๊ฒƒ์ด Props์ด๋‹ค.
๊ทธ๋ ‡๋‹ค๋ฉด ์ด์ œ Props๋ฅผ ์•Œ์•„๋ณด์ž.

profile
๊ฒ…๋ถ€ํ•˜์ž

0๊ฐœ์˜ ๋Œ“๊ธ€