๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

react

React / props, state ๋Œ์–ด์˜ฌ๋ฆฌ๊ธฐ

Props (property)

props๋Š” ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ž์‹ ์ปดํฌ๋„ŒํŠธ์—๊ฒŒ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•˜๋Š” ์ •๋ณด์˜ ์ง‘ํ•ฉ์œผ๋กœ, ๊ฐ์ฒด ํ˜•ํƒœ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ํฌํ•จํ•˜๊ณ  ์žˆ๋‹ค.

 

ํŠน์ง•

  • React ๋‚ด์—์„œ ์†์„ฑ์œผ๋กœ ์‚ฌ์šฉ๋จ
  • ์ฝ๊ธฐ์ „์šฉ(Read-only)์ž„
  • ๋ถ€๋ชจ๋กœ๋ถ€ํ„ฐ ์ „๋‹ฌ๋œ Props๋Š” ์ž์‹ ์ปดํฌ๋„ŒํŠธ์—์„œ ๋ณ€๊ฒฝ ๋ถˆ๊ฐ€๋Šฅ
    (์ •์˜๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์ •ํ•˜๋ ค๋ฉด ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณ€๊ฒฝํ•ด์•ผ ํ•จ)

 

์‚ฌ์šฉ ๋ฐฉ๋ฒ•

๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ

<์ž์‹ ์ปดํฌ๋„ŒํŠธ props์ด๋ฆ„ = {props} />

 

์ž์‹ ์ปดํฌ๋„ŒํŠธ 

// ํ•จ์ˆ˜ํ˜•
function ์ž์‹ ์ปดํฌ๋„ŒํŠธ ({props์ด๋ฆ„}){}

// ํด๋ž˜์Šคํ˜•
super(props)
props.props์ด๋ฆ„
// ๋˜๋Š”
this.props.props์ด๋ฆ„

 

 

์ด์ „ ๊ธ€(์ƒํƒœ๊ด€๋ฆฌ)์—์„œ ์‚ฌ์šฉํ–ˆ๋˜ counter ์ฝ”๋“œ๋ฅผ ์ด์šฉํ•ด์„œ props๋ฅผ ํ™•์ธํ•ด๋ณด๊ฒ ๋‹ค.

 

๊ฐ์ฒด ํ˜•ํƒœ๋กœ ์ „๋‹ฌ๋˜๊ณ  ์žˆ๋Š” props

 

๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ์—์„œ Count(์ž์‹ ์ปดํฌ๋„ŒํŠธ์˜ ์ด๋ฆ„) ์š”์†Œ๋ฅผ ๋งŒ๋“ค๊ณ , ๊ทธ ์•ˆ์— counter์™€ hello๋ผ๋Š” props๋ฅผ ์ „๋‹ฌํ–ˆ๊ณ ,

์ž์‹ ์ปดํฌ๋„ŒํŠธ์ธ Count์—์„œ ํŒŒ๋ผ๋ฏธํ„ฐ props๋ฅผ ์ถ”๊ฐ€ํ•ด ๋ฐ›์•„์™€ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

์‹ค์ œ๋กœ ์ค‘๊ฐ„์— hello prop๋ฅผ ์ถ”๊ฐ€ํ•œ ๋’ค๋กœ๋Š” hello๋„ ์ฝ˜์†”์ฐฝ์— ์ถœ๋ ฅ๋˜๊ณ  ์žˆ์Œ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

 

<Count counter={counter} />

 

์ด ๋•Œ ์™ผ์ชฝ์˜ counter๋Š” Count ์ปดํฌ๋„ŒํŠธ์—์„œ ๋ฐ›์„ props์˜ ์ด๋ฆ„,

์˜ค๋ฅธ์ชฝ {counter}๋Š” App ์ปดํฌ๋„ŒํŠธ์—์„œ ๊ด€๋ฆฌํ•˜๋Š” counter์˜ ์ƒํƒœ ๊ฐ’์ด๋‹ค.

App ์ปดํฌ๋„ŒํŠธ์—์„œ counter์˜ ์ƒํƒœ๋ฅผ Count์— ์ „๋‹ฌํ•ด ๊ฐ’์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ๊ฒƒ์ด๋‹ค. 

 

์œ„์ฒ˜๋Ÿผ props ๊ฐ์ฒด๋ฅผ ๋ชจ๋‘ ๊ฐ€์ ธ์™”์„ ๋•Œ counter ๋ฐ์ดํ„ฐ๋ฅผ ํ™”๋ฉด์— ๋ฐ˜์˜ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ์จ์ค„ ์ˆ˜ ์žˆ๋‹ค.

function Count(props) {
  console.log(props);
  return <div>counter : {props.counter}</div>
}

 

 

๋˜๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ตฌ์กฐ๋ถ„ํ•ดํ• ๋‹น์œผ๋กœ ๊ฐ€์ ธ์˜ฌ ์ˆ˜๋„ ์žˆ๋‹ค. 

๊ตฌ์กฐ๋ถ„ํ•ดํ• ๋‹น์„ ํ•  ๋•Œ๋Š” {}๋กœ ์ œ๋ฐœ ๊ผญ ๋ฌถ์–ด์ค˜์•ผํ•œ๋‹ค. ์•ˆํ•˜๋ฉด...

 

ํŒŒ๋ผ๋ฏธํ„ฐ์—์„œ ๋งจ ์•ž์— ์œ„์น˜ํ•ด์žˆ๋Š” counter์— props๊ฐ์ฒด๊ฐ€ ๋ชจ๋‘ ๋“ค์–ด๊ฐ€๊ฒŒ ๋˜๊ณ  hello๋ž‘ array๋Š” undefined๊ฐ€ ๋œ๋‹ค...

 

function App() {
  const [counter, setCounter] = useState(0)

  function increase() {
    setCounter((prev)=>prev+1);
  }

  function decrease() {
    setCounter((prev)=>prev-1);
  }
  return (
    <>
    <Count counter={counter} hello={"hello"} array={[1, 2, 3, "์•ˆ๋…•ํ•˜์„ธ์š”"]}/>
      <button onClick={increase}>+</button>
      <button onClick={decrease}>-</button>
    </>
  );
}

// {}๋กœ ๋ฌถ์–ด์„œ ๊ตฌ์กฐ๋ถ„ํ•ดํ• ๋‹น์œผ๋กœ ๊ฐ€์ ธ์˜ค๊ธฐ
function Count({counter, array, hello}) {
  console.log('array', array);
  console.log('counter', counter);
  console.log('hello', hello);
  return <div>counter : {counter}</div>
}

 

 

 

+ ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ๋กœ ๊ตฌ์„ฑํ•˜๊ธฐ

 

import { Component } from "react";
import "./App.css";

class App extends Component {
  state = { counter: 0 };
  increase = () => {
    this.setState((prevState) => ({
      counter: prevState.counter + 1,
    }));
  };

  decrease = () => {
    this.setState((prevState) => ({
      counter: prevState.counter - 1,
    }));
  };
  render() {
    return (
      <div>
        <Count counter={ this.state.counter }/>
        <button onClick={this.increase}>+</button>
        <button onClick={this.decrease}>-</button>
      </div>
    );
  }
}

class Count extends Component {
  // ๋ฐฉ๋ฒ• #1. constructor๋ฅผ ์ƒ์„ฑํ•ด super ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉ
  // ๋ฐฉ๋ฒ• #2. constructor ์ƒ์„ฑ ์•ˆํ•˜๊ณ  ๊ทธ๋ƒฅ ๋ฐ›์•„์˜ค๊ธฐ (๋งŒ์•ฝ ์ƒ์„ฑ ์•ˆํ•  ์‹œ ๊ธฐ๋ณธ์œผ๋กœ constructor๊ฐ€ ์ƒ์„ฑ๋˜๊ธฐ ๋•Œ๋ฌธ์ž„)
  constructor(props){
    super(props);
  }
  render(){
    return <div>counter : {this.props.counter}</div>
  }
}

export default App;

 

 

 


 

 

State ๋Œ์–ด์˜ฌ๋ฆฌ๊ธฐ 

 

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

 

 

 

#๋ฐฉ๋ฒ• 1 : ์ž์‹ ์ปดํฌ๋„ŒํŠธ์—์„œ ๊ณ„์‚ฐํ•˜๊ธฐ


์šฐ์„  ์œ„์˜ counter ์˜ˆ์ œ์—์„œ ๊ธฐ์กด์˜ ๋ฒ„ํŠผ๋“ค์„ PlusBtn, MinusBtn์˜ ์ปดํฌ๋„ŒํŠธ๋กœ ๋”ฐ๋กœ ์ƒ์„ฑํ–ˆ๋‹ค.

 

๊ทธ๋ฆฌ๊ณ  input ํ•˜๋‚˜๊ฐ€ ์ถ”๊ฐ€๋๋‹ค. ์ž์‹์ปดํฌ๋„ŒํŠธ CounterInput๋กœ ์ƒ์„ฑํ–ˆ๊ณ , input์˜ ์ƒํƒœ๋„ ๋”ฐ๋กœ ์„ ์–ธํ–ˆ๋‹ค. ๊ธฐ๋Šฅ์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.
* input์— ์ˆซ์ž๋ฅผ ์ž…๋ ฅ => ์ž…๋ ฅ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด counter์˜ ๊ฐ’์ด ๋ณ€๊ฒฝ => ํ™”๋ฉด์— ๋ฐ˜์˜

 

์ด ๋•Œ ์ž์‹ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๊ฐ๊ฐ const [counter, setCounter] = useState(0); ~~~ ๋“ฑ ์ƒํƒœ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค๋ฉด, ๋ฒ„ํŠผ๋ผ๋ฆฌ ์ƒํƒœ๊ฐ€ ๊ณต์œ ๋˜์ง€ ์•Š์•„ counter์˜ ๊ฐ’์ด ์—‰๋ง์ด ๋  ๊ฒƒ์ด๋‹ค. ํ•˜์ง€๋งŒ State๋ฅผ ๋Œ์–ด์˜ฌ๋ฆฌ๋ฉด ์ž์‹ ์ปดํฌ๋„ŒํŠธ์—์„œ ์ž์œ ๋กญ๊ฒŒ ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•ด ๋ถ€๋ชจ์—๊ฒŒ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋‹ค.

 

function App() {
  const [counter, setCounter] = useState(0);
  const [inputValue, setInputValue] = useState(5);

  return (
    <>
      <Count counter={counter} />
      <PlusBtn setCounter={setCounter} />
      <MinusBtn setCounter={setCounter} />
      <CounterInput inputValue={inputValue} setInputValue={setInputValue} setCounter={setCounter} />
    </>
  );
}


PlusBtn, MinusBtn ์ž์‹ ์ปดํฌ๋„ŒํŠธ๋“ค์—๊ฒŒ props์— setCounter๋ฅผ ๋‹ด์•„ ๋„˜๊ฒจ์คฌ๊ณ ,

CounterInput์—๊ฒŒ๋Š” input์˜ ์ƒํƒœ๊ฐ’๊ณผ ์ƒํƒœ ๋ณ€๊ฒฝ ํ•จ์ˆ˜, ๊ทธ๋ฆฌ๊ณ  counter์˜ ๊ฐ’๋„ ๋ณ€๊ฒฝํ•ด์ฃผ๊ธฐ ์œ„ํ•ด setCounter๊นŒ์ง€ props์œผ๋กœ ๋„˜๊ฒจ์คฌ๋‹ค.

 

์ž์‹ ์ปดํฌ๋„ŒํŠธ์—์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ฒ„ํŠผ ์š”์†Œ์™€ ์ƒํƒœ๋ฅผ ์ง์ ‘ ๋ณ€๊ฒฝํ•˜๊ณ  ์žˆ๋‹ค.

 

function PlusBtn({ setCounter }) {
  return (
    <button onClick={() => { setCounter(prev => prev + 1); }}>+</button>
  );
}

function MinusBtn({ setCounter }) {
  return (
    <button onClick={() => { setCounter(prev => prev - 1); }}>-</button>
  );
}

function Count({ counter }) {
  return <div>counter : {counter}</div>;
}

 

 

CounterInput ์ปดํฌ๋„ŒํŠธ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

function CounterInput({ inputValue, setInputValue, setCounter }) {
  return (
    <div>
      <input type="number" value={inputValue} onChange={e => setInputValue(e.target.value)} />
      <button onClick={() => setCounter(inputValue)}>์ž…๋ ฅ</button>
    </div>
  );
}

 

input์˜ value๊ฐ’์„ {inputValue}๋กœ ์„ค์ •ํ–ˆ๊ณ , onChange ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•  ๊ฒฝ์šฐ setInputValue์˜ ๊ฐ’์„ ์ด๋ฒคํŠธ ํƒ€๊ฒŸ์˜ value(์ฆ‰ input์— ์ ์€ ๊ฐ’)

๋งŒ์•ฝ onChange์ด๋ฒคํŠธ๋ฅผ ์„ค์ •ํ•˜์ง€ ์•Š์œผ๋ฉด ์ฒ˜์Œ ์„ ์–ธํ•  ๋•Œ์˜ useState(5)์—์„œ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š๋Š”๋‹ค.

 

๊ทธ๋ฆฌ๊ณ  ์œ„์™€ ๊ฐ™์€ ๊ฒฝ๊ณ ๋ฅผ ๋„์›Œ์ค€๋‹ค!

 

๊ทธ๋ฆฌ๊ณ  ์ž…๋ ฅ ๋ฒ„ํŠผ์— onClick ์ด๋ฒคํŠธ๋ฅผ ์ถ”๊ฐ€ํ•ด ํด๋ฆญ ์‹œ setCounter๋กœ counter์˜ ๊ฐ’์ด inputValue์˜ ๊ฐ’์œผ๋กœ ๋ณ€๊ฒฝ๋˜๊ฒŒํ•œ๋‹ค.

์ด ๋•Œ ์ด๋ ‡๊ฒŒ input ์š”์†Œ์˜ ๊ฐ’๊ณผ ๋ฆฌ์•กํŠธ์˜ ์ƒํƒœ์™€ ์™„์ „ํžˆ ์—ฐ๋™๋˜์–ด์žˆ์„ ๋•Œ, ํ•ด๋‹น ์ปดํฌ๋„ŒํŠธ๋ฅผ Controlled Component ๋ผ๊ณ ๋„ ํ•œ๋‹ค.

 

 

 

#๋ฐฉ๋ฒ• 2.  ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ์—์„œ ๊ณ„์‚ฐ ํ•จ์ˆ˜๋ฅผ ๋‚ด๋ ค์ฃผ๊ธฐ

 

onClick์‹œ ์ƒํƒœ๋ฅผ ์ง์ ‘ ๋ณ€๊ฒฝํ•ด์ฃผ๋Š” ๋ถ€๋ถ„์„ ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ์—์„œ ํ•จ์ˆ˜๋ฅผ ํ‘œํ˜„ํ•˜๊ณ , ํ•จ์ˆ˜๋ฅผ props๋กœ ๋ณด๋‚ด๊ณ  ์žˆ๋‹ค. 

๊ทธ๋ฆฌ๊ณ  ํด๋ฆญ ์‹œ counter์˜ ๊ฐ’์„ inputValue๋กœ ๋ฐ”๊ฟ”์ฃผ๋Š” ํ•จ์ˆ˜ setCounternumber๋ฅผ ์ถ”๊ฐ€ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์—,

CounterInput ์ปดํฌ๋„ŒํŠธ์—๋„ ๊ธฐ์กด์˜ setCounter๊ฐ€ ์•„๋‹Œ setCounternumber๋ฅผ props๋กœ ๋„˜๊ฒจ์ฃผ๊ณ  ์žˆ๋‹ค.

 

function App() {
  const [counter, setCounter] = useState(0);
  const [inputValue, setInputValue] = useState(5);

  const incrementCounter = () => {
    setCounter(counter + 1);
  };
  const decrementCounter = () => {
    setCounter(counter - 1);
  };
  const setCounternumber = () => {
    setCounter(inputValue);
  };

  return (
    <>
      <Count counter={counter} />
      <PlusBtn incrementCounter={incrementCounter} />
      <MinusBtn decrementCounter={decrementCounter} />
      <CounterInput inputValue={inputValue} setInputValue={setInputValue} setCounternumber={setCounternumber} />
    </>
  );
}

 

์ž์‹ ์ปดํฌ๋„ŒํŠธ๋“ค์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

setCounterํ•ด์ฃผ๋Š” ์‹คํ–‰๋˜๋Š” ๋‚ด์šฉ์„ ๋ถ€๋ชจ์—์„œ ์„ ์–ธํ•ด props๋กœ ๋‹ค ๋ณด๋ƒˆ๊ธฐ ๋•Œ๋ฌธ์— onClick์‹œ ์‹คํ–‰ ๋‚ด์šฉ ํ•จ์ˆ˜๋ฅผ ๊ทธ๋Œ€๋กœ ๋„ฃ์–ด์ฃผ๋ฉด ๋œ๋‹ค.

 

function CounterInput({ inputValue, setInputValue, setCounternumber }) {
  return (
    <div>
      <input type="number" value={inputValue} onChange={e => setInputValue(e.target.value)} />
      <button onClick={setCounternumber}>์ž…๋ ฅ</button>
    </div>
  );
}

function PlusBtn({ incrementCounter }) {
  return <button onClick={incrementCounter}>+</button>;
}

function MinusBtn({ decrementCounter }) {
  return <button onClick={decrementCounter}>-</button>;
}

function Count({ counter }) {
  console.log('counter', counter);
  return <div>counter : {counter}</div>;
}

 

 

 

+ ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ๋กœ ๊ตฌ์„ฑํ•˜๊ธฐ

 

class App extends Component {
  state = { counter: 0 };

  incrementCounter = () => {
    this.setState({counter : this.state.counter + 1})
  };
  decrementCounter = () => {
    this.setState({counter : this.state.counter - 1})
  }

  render() {
    return (
      <>
        <Count counter={ this.state.counter }/>
        <PlusBtn incrementCounter={this.incrementCounter}/>
        <MinusBtn decrementCounter={this.decrementCounter} />
      </>
    );
  }
}

class PlusBtn extends Component {
  render(){
    return (
      <button onClick={this.props.incrementCounter}>+</button>
    )
  }
}

class MinusBtn extends Component {
  render(){
    return (
      <button onClick={this.props.decrementCounter}>-</button>
    )
  }
}

class Count extends Component {
  render(){
    return <div>counter : {this.props.counter}</div>
  }
}