[React] Movie-app Notes - Props

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

[React] Movie-App

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

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


# 4. Props

Props(Properties)

์ปดํฌ๋„ŒํŠธ์— '์ผ๋ฐฉํ–ฅ์ ์œผ๋กœ' ์ „๋‹ฌํ•˜๋Š” ๊ฐ’
๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ๋กœ๋ถ€ํ„ฐ ์ž์‹ ์ปดํฌ๋„ŒํŠธ์— ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๋‚ผ ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๋Š” ์œ„ํ•ด props๊ฐ€ ํ•„์š”ํ•˜๋‹ค

State Practice์—์„œ ๋งŒ๋“ค์—ˆ๋˜ ์ปดํฌ๋„ŒํŠธ๋Š” ์ž์‹ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋…๋ฆฝ์ ์œผ๋กœ ์กด์žฌํ•  ์ˆ˜ ์žˆ๋‹ค.
์ž์‹ ์ปดํฌ๋„ŒํŠธ MinsToHrs, KmToMile๊ฐ€ ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ App()์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๊ทธ๋‹ค์ง€ ํ•„์š”๋กœ ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ์•„๋ž˜์—์„œ๋Š” ๋ฐ์ดํ„ฐ ์ „๋‹ฌ์„ ์œ„ํ•œ ์ƒˆ๋กœ์šด ์˜ˆ์‹œ๋ฅผ ๋งŒ๋“ค ๊ฒƒ์ด๋‹ค.

Props ์‚ฌ์šฉํ•˜์ง€ ์•Š์„ ๋•Œ

<script type="text/babel">
  function ResetBtn() {
    return (
      <button
        style={{
          backgroundColor: 'red',
          border: 0, // == border: 'none',
          borderRadius: 20,
          padding: 10,
          color: 'white',
          margin: '10px',
        }}
      >
        reset
      </button >
    )
  }
  function ConfirmBtn() {
    return (
      <button
        style={{
          backgroundColor: 'blue',
          border: 0, // == border: 'none',
          borderRadius: 20,
          padding: 10,
          color: 'white',
          margin: '10px',
        }}
      >
        confirm
      </button >
    )
  }

  function App() {
    return (
      <div>
        <ResetBtn />
        <ConfirmBtn />
      </div>)
    // Btn์„ ์†Œ๋ฌธ์ž๋กœ ์ ์–ด์„œ ๊ณ„์† ์—๋Ÿฌ๊ฐ€ ๋‚ฌ์—ˆ๋‹ค.
  }


  const root = document.getElementById("root")
  ReactDOM.render(<App />, root);
</script>

props๋ฅผ ์ „๋‹ฌํ•˜์ง€ ์•Š์„ ๋•Œ๋Š” ๊ฐ™์€ ์—ญํ• ์„ ํ•˜๋Š” ๋ฒ„ํŠผ์ด๋ผ๋„ ๋‹ค๋ฅธ ์†์„ฑ๊ฐ’์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ™์€ ์ฝ”๋“œ๋ฅผ ๋ฐ˜๋ณตํ•ด์•ผ ํ–ˆ๋‹ค. ๋ฒ„ํŠผ์˜ ๋กœ์ง์ด ๊ฐ™์ง€๋งŒ BackgroundColor๊ฐ€ ๋‹ค๋ฅด๊ณ , ๋ฒ„ํŠผ์˜ ๋‚ด์šฉ์ด ๋‹ค๋ฅด๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ™์€ ์ฝ”๋“œ๋ฅผ ๋‘ ๋ฒˆ ๋‚˜๋ˆ„์–ด ์“ฐ๊ฒŒ ๋˜์—ˆ๋‹ค.
์ด ๋•Œ, props๋ฅผ ์ด์šฉํ•ด ๋ณ€ํ™”๋˜๋Š” ์†์„ฑ๋งŒ ๋”ฐ๋กœ ์ „๋‹ฌ์„ ํ•œ๋‹ค๋ฉด ๋ถˆํ•„์š”ํ•œ ๋ฐ˜๋ณต์„ ์ค„์ผ ์ˆ˜ ์žˆ๋‹ค.

Props๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด

<script type="text/babel">
  function Btn({ name, color }) {
    console.log(color);
    return (
      <button
        style={{
          backgroundColor: color,
          border: 0, // == border: 'none',
          borderRadius: 20,
          padding: 10,
          color: 'white',
          margin: '10px',
        }}
      >
        {name}
      </button >
    )
  }

  function App() {
    return (
      <div>
        <Btn name="reset" color="red" />
        <Btn name="confirm" color="blue" />
      </div>)
    // Btn์„ ์†Œ๋ฌธ์ž๋กœ ์ ์–ด์„œ ๊ณ„์† ์—๋Ÿฌ๊ฐ€ ๋‚ฌ์—ˆ๋‹ค.
  }


  const root = document.getElementById("root")
  ReactDOM.render(<App />, root);
</script>

๋ˆˆ์— ๋„๋Š” ์ฐจ์ด์ ์€

  1. button์ด๋ผ๋Š” ๊ณตํ†ต์˜ ์—ญํ• ์„ ํ•˜๋Š” <Btn /> Component ๋‹จ์ผํ™”
  2. <Btn /> Component์—์„œ ์ธ์ž๋กœ ๋„˜๊ฒจ์ฃผ๋Š” name, color
  3. backgroundColor: color, {name}์ฒ˜๋Ÿผ ๋ณ€์ˆ˜๋กœ ์“ฐ์ด๋Š” 2๋ฒˆ์˜ ๊ฐ’
  4. App()์—์„œ ์ตœ์ข…์ ์œผ๋กœ rendering๋˜๋Š” <Btn /> Component ํ˜•ํƒœ
 	<Btn name="reset" color="red" />
 	<Btn name="confirm" color="blue" />

Props๋Š” ๋ฐ”๋กœ

name, color => props
<Btn />์ด๋ผ๋Š” ๊ณตํ†ต ์ปดํฌ๋„ŒํŠธ์— ๋ณ€ํ•ด์•ผ ํ•˜๋Š” ์†์„ฑ, ๋ฒ„ํŠผ์˜ ๋‚ด์šฉ=name๊ณผ ์ƒ‰์ƒ=color์„ props๋กœ ์ฃผ๋ฉฐ <Btn />์ปดํฌ๋„ŒํŠธ๋ฅผ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ๋‹ค.

์ž์‹ ์ปดํฌ๋„ŒํŠธ์˜ ํŒŒ๋ผ๋ฏธํ„ฐ ๊ฐ’์€ ์˜ค์ง ํ•˜๋‚˜, props์˜ {์˜ค๋ธŒ์ ํŠธ}์ด๋‹ค.
<Btn />์ปดํฌ๋„ŒํŠธ์— ์†์„ฑ์œผ๋กœ ๋„ฃ์€ ๋ชจ๋“  ๊ฐ’๋“ค์ด props๋ผ๋Š” {์˜ค๋ธŒ์ ํŠธ}์— ๋‹ด๊ฒจ ์ „๋‹ฌ๋œ๋‹ค.

	function Btn(props) === function Btn({name, color})

Props๋Š” number, string, boolean, ํ•จ์ˆ˜ ๋“ฑ ์—ฌ๋Ÿฌ ํ˜•ํƒœ๋กœ ์ „๋‹ฌ ๊ฐ€๋Šฅํ•˜๋‹ค.

<script type="text/babel">
  function Btn({ name, onClick }) {
    return (
      <button
        onClick={onClick}
        style={{
          backgroundColor: 'gray',
        }}
      >
        {name}
      </button >
    )
  }

  function App() {
    const [value, setValue] = React.useState("origin"); //name default ์„ค์ •
    const changeValue = () => setValue("change");

    return (
      <div>
        <Btn name={value} onClick={changeValue} />
        <Btn name="reset" />
      </div>)
  }
  const root = document.getElementById("root")
  ReactDOM.render(<App />, root);
</script>

์ด์ฒ˜๋Ÿผ onClick ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค์–ด prop์œผ๋กœ ์ „๋‹ฌํ•ด ๋ฒ„ํŠผ์˜ name์ด ๋ฐ”๋€” ์ˆ˜ ์žˆ๋„๋ก ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

๐Ÿ“Œ Check Point

์—ฌ๊ธฐ์„œ App()์˜ <Btn />์—์„œ ์“ฐ์ธ onClick={changeValue} ์€ ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ๊ฐ€ ์•„๋‹ˆ๋ผ prop์ด๋‹ค!
๋‹จ์ง€ ์ด๋ฆ„์ด onClick์ธ prop์ด๋‹ค. ๋งŒ์•ฝ <button onClick={}>๊ฐ™์ด HTML ์†์„ฑ์— ๋„ฃ์—ˆ๋‹ค๋ฉด ๊ทธ๊ฒƒ์€ ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ์ด๋‹ค. ํ•˜์ง€๋งŒ <Btn />์ฒ˜๋Ÿผ ์ปค์Šคํ…€ ์ปดํฌ๋„ŒํŠธ์— ๋„ฃ๋Š”๋‹ค๋ฉด ๊ทธ๊ฑด ๋‹จ์ง€ prop์ผ ๋ฟ์ด๋‹ค. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— onClick ์ด๋ฒคํŠธ๋ฅผ ์„ค์ •ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ์œ„์˜ ์ฝ”๋“œ์ฒ˜๋Ÿผ prop์„ ๋งค๊ฐœ ๋ณ€์ˆ˜๋กœ ์ „๋‹ฌํ•ด์•ผ ํ•œ๋‹ค.
๋ฐ˜๋Œ€๋กœ, <Btn style={{color : "green"}} />์€ ์ ์šฉ๋˜์ง€ ์•Š๋Š”๋‹ค. <Btn />์€ HTML ํƒœ๊ทธ๊ฐ€ ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

Props ์ „๋‹ฌ ํ˜•ํƒœ

props ์ž์ฒด๋กœ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ „๋‹ฌํ•œ๋‹ค๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ์จ์•ผ ํ•œ๋‹ค.

  • {name} => {props.name}
  • color => props.color
  function Btn(props) {
    return (
      <button
        style={{
          backgroundColor: props.color,
          border: 0, // == border: 'none',
          borderRadius: 20,
          padding: 10,
          color: 'white',
          margin: '10px',
        }}
      >
        {props.name}
      </button >
    )
  }

ํ•˜์ง€๋งŒ ๊ฐœ๋ฐœ์ž๋“ค์€ shortcut์„ ์ข‹์•„ํ•˜๋‹ˆ๊นŒ..ใ…Žใ…Ž

Prop Type

Prop์— ํ˜•์‹์ด ์ •ํ•ด์ ธ ์žˆ๋Š” ๊ฒƒ์€ ์•„๋‹ˆ์ง€๋งŒ, ๊ฐœ๋ฐœ ์˜๋„์— ๋”ฐ๋ผ ํ˜•์‹์„ ์ง€์ผœ์•ผ ํ•  ๋•Œ๊ฐ€ ๋งŽ๋‹ค. ํ•˜์ง€๋งŒ ์ฝ”๋“œ๋ฅผ ์งœ๋‹ค ์‹ค์ˆ˜๋ฅผ ํ•  ์ˆ˜๋„ ์žˆ๊ณ , ๊ฐœ๋ฐœ์ž๋“ค๊ฐ„ ํ˜‘์—…์„ ํ•˜๋‹ค๋ณด๋ฉด ์†Œํ†ต์˜ ๋ถ€์žฌ๋กœ Prop์˜ ์ „๋‹ฌ์— ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜๋„ ์žˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ์œ„์ฒ˜๋Ÿผ name์€ string ํƒ€์ž…์ด์–ด์•ผ ํ•˜์ง€๋งŒ name์— ์ˆซ์ž๋ฅผ ๋„ฃ๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค๋ฉด? ์•ฑ ๊ตฌํ˜„์˜๋„์—์„œ ๋ฒ—์–ด๋‚  ๊ฒƒ์ด๋‹ค.
์ด๋Ÿด ๋•Œ ํ•„์š”ํ•œ ๊ฒƒ์ด Prop Type์ด๋‹ค.

Prop Type์€ ๋ง ๊ทธ๋Œ€๋กœ Prop์— ํƒ€์ž…์„ ์ •ํ•ด์ฃผ๋Š” ๊ฒƒ์ด๋‹ค.
ํ˜น์‹œ๋‚˜ ๊ทœ์•ฝ์„ ๋”ฐ๋ฅด์ง€ ์•Š์•˜์„ ๊ฒฝ์šฐ, ์—๋Ÿฌ๋ฅผ ๋Œ€๋น„ํ•ด ์„ค์น˜ํ•˜๋Š” ๋ณดํ—˜์ด๋ผ๊ณ  ๋ณผ ์ˆ˜ ์žˆ๋‹ค.
ํƒ€์ž…์„ ์‚ฌ์šฉํ•˜๋ ค๋ฉด Prop Type ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์„ค์น˜๊ฐ€ ํ•„์š”ํ•˜๋‹ค. ์Šคํฌ๋ฆฝํŠธ์— ์ถ”๊ฐ€ํ•ด์ฃผ์ž.

<script src="https://unpkg.com/prop-types@15.7.2/prop-types.js"></script>

Origin Code

<script type="text/babel">
  function Btn({ name, onClick, padding }) {
    return (
      <button
        onClick={onClick}
        style={{
          backgroundColor: 'gray',
          border: 0,
          borderRadius: padding,
          padding, // === padding: padding,
          color: 'white',
          margin: '10px',
        }}>
        {name}
      </button >
    )
  }
  function App() {
    const [value, setValue] = React.useState("origin");
    const changeValue = () => setValue("change");
    return (
      <div>
        <Btn name={value} onClick={changeValue} padding={20} />
        <Btn name="reset" padding={30} />
      </div>)
  }
  const root = document.getElementById("root")
  ReactDOM.render(<App />, root);
</script>

์˜ค๋ฅ˜๋ฐœ์ƒ

  function App() {
    const [value, setValue] = React.useState("origin");
    const changeValue = () => setValue("change");
    return (
      <div>
        <Btn name={value} onClick={changeValue} padding={20} />
        <Btn name={30} padding='reset' />	{/* ์˜ค๋ฅ˜ ๋ฐœ์ƒ์ง€์  */}
      </div>)
  }

์—ฌ๊ธฐ์„œ name๊ณผ padding์˜ ๊ฐ’์ด ๋ฐ”๋€Œ์–ด ์ž…๋ ฅ์ด ๋˜์—ˆ์„ ๊ฒฝ์šฐ, <Btn />์€ ๋‚ด๊ฐ€ ๋งŒ๋“  ์ปดํฌ๋„ŒํŠธ์ด๊ธฐ ๋•Œ๋ฌธ์— React๋Š” ๋ฌด์—‡์ด ์ž˜ ๋ชป ๋๋Š”์ง€ ์•Œ ์ง€ ๋ชปํ•œ๋‹ค.

์—๋Ÿฌ๋ฉ”์„ธ์ง€๊ฐ€ ์—†๋‹ค.

์ด๋Ÿฌํ•œ ๊ฒฝ์šฐ์—์„œ ํƒ€์ž…์„ ์ง€์ •ํ•ด์ค€๋‹ค๋ฉด?


 // ํ”„๋กญ์— **ํƒ€์ž…**์„ ์ฃผ๋Š” ๋ฐฉ๋ฒ•
  Btn.propTypes = {
    name: PropTypes.string,
    padding: PropTypes.number,
  }

  function App() {
 ...
  }
   

์ฝ˜์†”์—์„œ ํƒ€์ž…์ด ๋งž์ง€ ์•Š๋‹ค๋ฉฐ ๊ฒฝ๊ณ ํ•ด ์ค€๋‹ค.

๋˜, ๊ผญ ํ•„์š”ํ•œ ๊ฐ’์ด ์žˆ๋‹ค๋ฉด isRequired๋ฅผ ์ ์šฉํ•˜๋ฉด ๋œ๋‹ค.

  return (
      <div>
        <Btn name={value} onClick={changeValue} padding={20} />
        <Btn padding={30} />
      </div>)

2๋ฒˆ์งธ ๋ฒ„ํŠผ์— name ๊ฐ’์„ ๋นผ๋จน์—ˆ๋‹ค.

๊ตฌ๋™์€ ๋˜์ง€๋งŒ ์ฝ˜์†”์ฐฝ์ฒ˜๋Ÿผ name์ด required, ๊ผญ ํ•„์š”ํ•œ prop์ž„์„ ์•Œ๋ ค์ฃผ๊ณ  ์žˆ๋‹ค.
๊ฐ’์„ ์ง€์ •ํ•˜์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์— undefined๋กœ ์ ์šฉ์ด ๋œ ๋ชจ์Šต์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

์ด์ฒ˜๋Ÿผ, Prop Type์„ ์‚ฌ์šฉํ•ด ์˜๋„๋ฅผ ๋ช…ํ™•ํ•˜๊ฒŒ ํ‘œ์‹œํ•  ์ˆ˜ ์žˆ๋‹ค.
Prop์ด ์–ด๋–ค ํƒ€์ž…์œผ๋กœ ์“ฐ์—ฌ์•ผ ํ•˜๋Š”์ง€, ์ด ์†์„ฑ์€ ์ƒ๋žต ๊ฐ€๋Šฅํ•œ ์†์„ฑ์ธ์ง€ ์•„๋‹Œ์ง€ ๋ช…ํ™•ํ•˜๊ฒŒ ์ง‘๊ณ  ๋„˜์–ด๊ฐˆ ์ˆ˜ ์žˆ๋‹ค.

์˜๋„๋Œ€๋กœ ์ž‘๋™๋œ ๋ชจ์Šต


Summary

Component๋ฅผ ๋ฐ˜๋ณตํ•ด ์žฌ์‚ฌ์šฉํ•  ๋•Œ, ๋ฐ”๋€Œ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ์ด props์ด๋‹ค.
๋ฆฌ์•กํŠธ์˜ Key - 'ํ•„์š”ํ•œ ๋ถ€๋ถ„๋งŒ re-rendering'ํ•˜๋Š” ๊ฒƒ์ด props๋กœ ํ•˜์—ฌ๊ธˆ ๋”์šฑ interactive ํ•ด ์งˆ ์ˆ˜ ์žˆ๋‹ค.

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

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