프론트엔드 개발/React

React) props가 setState함수도 물려줄 수 있다네!

Ella Seon 2022. 11. 23. 17:44

- 정말 쉬운 예제코드라서 초보자들도 무리없이 이해할수있습니다.

 

 

1. 오늘의 삽질 원인

- props 실습을 하다가, props는 state와 문자,숫자 종류만 자식에게 물려줄 수 있는 줄 알았다.

- 하지만, setState 함수도 물려줄 수 있었다.

- 그런데, 알고있기로 props를 통해서 state를 물려줄때에는 state를 변경 불가능하다고 알고있었다.

즉, readonly라고만 알고있었는데...

setState함수를 쓰니...자식의 값을 바꿔버리니 부모의 값도 바뀌는 것이었다... 또르르...

 

나는 자식의 값만 바꾸고 싶었는데, 부모의 값도 같이 바꿔버렸다...

1-1) 예제코드

- App.js 파일에 

Main 자식 컴포넌트 안에 setState함수를 물려줄 이름을 

이름변경이라고 짓고, 스테이트변경함수 {setName}을 집어넣었다.

//App.js

/*eslint-disable*/
import { useState } from "react";
import Main from "./components/Main";

function App() {
  const [names, setName] = useState(["선은혜", "이태민", "송형준"]);

  return (
    <div>
      <h1>인삿말</h1>
      <p>안녕하세요 {names[0]}입니다.</p>
      <p>안녕하세요 {names[1]}입니다.</p>
      <p>안녕하세요 {names[2]}입니다.</p>
      <Main 이름목록 ={names} color={'red'} 이름변경={setName}/>
    </div>
  );
}

export default App;

 

- 이름-영어로-바꾸기 버튼을 클릭하면 Main 의 setName 을 받아와서 이름을 영어로 바꾸려고 했음

//Main.js


import {useState} from 'react'

export default function Main(props){ 


  function changeEn(){
    let copy = [...props.이름목록]
    copy[0] = 'seoneunhye'
    copy[1] = 'leetaemin'
    copy[2] = 'songhyungjoon'
    props.이름변경(copy)
  }


  return(
    <div>
      <h2 style={{color:props.color}}>자기소개</h2>
      <button
        onClick={changeEn}>이름-영어로-바꾸기</button>
      <p>잘부탁드립니다. {props.이름목록[0]}입니다.</p>
      <p>잘부탁드립니다. {props.이름목록[1]}입니다.</p>
      <p>잘부탁드립니다. {props.이름목록[2]}입니다.</p>
    </div>
  )
}

 

- 실행결과

 

버튼을 누르니... props는 자식은 readonly라서 부모의 데이터를 못바꿀줄 알았는데...

부모 컴포넌트인 App의 useState인 {names}까지 싸그리 다 바꿔버렸다... ㅜㅜ

부모의 state를 자식이 물려받으면, 자식은 부모의 데이터를 바꿀수 없지만,

setState를 물려받으면 자식이 setState를 바꿀때 부모의 값도 같이 변경된다는 것을 알았다.

 

2. 자식만 바꾸려면 부모 컴포넌트에서 setState함수를 물려받는게 아니라, 자식컴포넌트에서 따로 useState를 만들어야한다.

 

//자식컴포넌트인 Main.js

/*eslint-disable */
import {useState} from 'react'

export default function Main(props){ 

let [names,setNames] = useState([...props.이름목록])


function changeEn(){
  let copy = [...names];
  copy[0] = 'seoneunhye';
  copy[1] = 'leetaemin';
  copy[2] = 'sonhyungjoon';
  setNames(copy)
}

  return(
    <div>
      <h2 style={{color:props.color}}>자기소개</h2>
      <button
        onClick={changeEn}>이름-영어로-바꾸기</button>
      <p>잘부탁드립니다. {names[0]}입니다.</p>
      <p>잘부탁드립니다. {names[1]}입니다.</p>
      <p>잘부탁드립니다. {names[2]}입니다.</p>
    </div>
  )
}

 

 

3. 가나다순 정렬버튼을 만들어서 이름을 가나다로 정렬해보자

//자식컴포넌트인 Main.js

/*eslint-disable */
import {useState} from 'react'

export default function Main(props){ 

let [names,setNames] = useState([...props.이름목록])

let copy = [...names]; //changeEn과 sortNames함수가 모두 copy를 쓸테니 전역변수로 만들자

function changeEn(){
  copy[0] = 'seoneunhye';
  copy[1] = 'leetaemin';
  copy[2] = 'sonhyungjoon';
  setNames(copy)
}

function sortNames(){
  setNames(copy.sort())
}

  return(
    <div>
      <h2 style={{color:props.color}}>자기소개</h2>
      <button
        onClick={changeEn}>이름-영어로-바꾸기</button>
      <button
        onClick={sortNames}>가나다순 정렬</button>
      <p>잘부탁드립니다. {names[0]}입니다.</p>
      <p>잘부탁드립니다. {names[1]}입니다.</p>
      <p>잘부탁드립니다. {names[2]}입니다.</p>
    </div>
  )
}

 

4. 결론 

- props 값은 자식컴포넌트 내부에서 변경할 수 없다. 넘겨받은 그대로 사용해야한다. setState를 부모에게 넘겨받아서 자식값을 변경하면 부모의 값도 그대로 바뀌어 버린다.

- 만일, 자식컴포넌트의 값만 변경하고싶다면 컴포넌트 내부에서 useState를 만들어서 값을 변경해야한다.