React

[새싹 프론트앤드] 리액트 state, useState 함수, state 끌어올리기

화영강 2022. 12. 4. 03:18

1. state란?

* state

값을 저장하거나 변경할 수 있는 객체

컴포넌트 내부에서 바뀔 수 있는 값을 의미

주로 버튼 클릭과 같은 이벤트와 함께 사용

ex) 장바구니 수량 추가, 댓글 남기기 등

 

 

* props와 차이점

: props는 부모 컨포넌트에서 값을 받아 읽기 전용으로 사용한다.

state와 다르게 컴포넌트 내부에서 값을 직접 변경할 수 없다.

 

 

 

2. 함수형 컴포넌트의 useState

* 배열 비구조화 할당 : 배열 안에 들어있는 값을 쉽게 추출할 수 있도록 해주는 문법

const array = [1, 2]
const [one, two] = array;

array에 있는 배열의 값들이 각각 변수 one, two에 저장된다.

 

 

* useState 함수

const [value, setValue] = useState(값);

- value : 현재상태 = 현재 값

- setValue : value의 상태/값을 바꿔주는 함수

- 값 : value의 초기값,  숫자, 문자, 객체, 배열 등이 들어갈 수 있다

 

 

* useState 값 가져오는 방법 : useState의 첫번째 원소를 {}로 묶어 return에 넣으면 값이 출력된다

- 위에 import React, {useState} from 'react'; 작성

- 한 컴포넌트에서 useState 여러 개 사용 가능

 

 

 

3. state와 이벤트 연동 (값 변경X)

< button onClick={클릭 시 실행 함수} >클릭</button>

function 클릭 시 실행 함수() {

// 실행내용

}

* 버튼을 클릭하면 실행되는 함수를 따로 정의 해야 한다.

 

 

 

4. state 값 변경하기

: useState 함수의 두번째 원소를 이용한다.

const [value, setValue] = useState(값);

 

그냥 value = "apple" 이런 방식으로는 변경이 안되고 setValue() 함수를 이용해야한다.

setValue('apple');

 

import React, { useState } from "react";

function ChangeValue() {
  const [value, setValue] = useState("안녕하세요");
  //value를 변경하는 함수를 만들어주고 실행내용에 setValue('변경값') 넣어주기

  function changeValue() {
    //클릭하면 value가 반가워요로 변경
    setValue("반가워요");
  }

  return (
    <div>
      <h1>{value}</h1>
      <button onClick={changeValue}>클릭</button>
    </div>
  );
}

export default ChangeValue;

 

 

객체 또는 배열의 state 값 변경

객체 또는 배열의 복사본을 만들어 값을 업데이트 한 후 복사본의 상태를 useState()함수를 통해 업데이트

 

* 사본만들기 : spread 연산자(...배열명) 사용

객체/배열의 기존 내용을 변경하지 않고, 새로운 객체/ 배열을 생성한다.

 

const copyObject = { ...object, b: 50}

-> 이렇게 하면 objcet의 기존 값들은 그대로 출력되고 변하는 값을 뒤에 추가해주면 그 값만 변경된다.

변경값은 copyObject에 저장된다.

 

이렇게 등호연산자를 이용하면 세 객체가 같은 데이터 공간을 가리켜 똑같은 값을 가지게 된다.

 

 

import React from "react";

function Spread() {
  const person1 = { name: "화영" };
  const person2 = { ...person1, age: 20 };
  const person3 = { ...person2, region: "seoul" };

  return (
    <div>
      <h1>{JSON.stringify(person1)}</h1>
      <h1>{JSON.stringify(person2)}</h1>
      <h1>{JSON.stringify(person3)}</h1>
    </div>
  );
}

export default Spread;

스프레드 연산자를 사용하면 각 객체가 서로 다른 데이터 공간을 가지므로 각각 다른 데이터가 저장된다.

-> 영역도 새롭게 가진다

 

 

* 키값을 추가하지 않고 값 변경만 해줘도 데이터 저장이 이루어진다.

import React from "react";

function Spread() {
  const person1 = { name: "화영" };
  const person2 = { ...person1, age: 20 };
  const person3 = { ...person2, region: "seoul" };
  const person4 = { ...person3, region: "부산" };

  return (
    <div>
      <h1>{JSON.stringify(person1)}</h1>
      <h1>{JSON.stringify(person2)}</h1>
      <h1>{JSON.stringify(person3)}</h1>
      <h1>{JSON.stringify(person4)}</h1>
    </div>
  );
}

export default Spread;

 

 

* 스프레드가 뒤로 간다면?

앞에 새로운 값을 저장하고 스프레드 연산자를 가져오면 기존값이 나중에 온 값에 덮어지게 된다.

import React from "react";

function Spread() {
  const person1 = { name: "화영" };
  const person2 = { ...person1, age: 20 };
  const person3 = { ...person2, region: "seoul" };
  const person4 = { region: "부산", ...person3 };

  return (
    <div>
      <h1>{JSON.stringify(person1)}</h1>
      <h1>{JSON.stringify(person2)}</h1>
      <h1>{JSON.stringify(person3)}</h1>
      <h1>{JSON.stringify(person4)}</h1>
    </div>
  );
}

export default Spread;

 

 

*state값 변경하기  - 배열

import React, { useState } from "react";

function ChangeArray() {
  const [value, setValue] = useState(["안녕", "하이"]);

  function ChangeArray() {
    var cValue = [...value];
    cValue = "Hello";
    //여기까지 하면 값이 변경되지 않고 setValue까지 해야 한다.
    setValue(cValue);
  }
  return (
    <div>
      <h1>{value[0]}</h1>
      <h1>{value[1]}</h1>
      <button onClick={ChangeArray}>배열 값 변경</button>
    </div>
  );
}

export default ChangeArray;

 

배열 cValue에 스프레드 연산자를 넣고 1번 인덱스 값을 변경한다.

cValue를 setValue 함수를 이용하여 value를 변경한다.

 

 

 

5. state 끌어올리기(Lifting State Up)

- 형제 컴포넌트 간에 데이터를 공유 할 수 없다. 

- 해당 값을 필요로 하는 컴포넌트 간의 가장 가까운 공통 조상으로 state를 끌어올려 공유할 수 있다.

- 상위 컴포넌트의 '상태를 변경하는 함수'  그 자체를 하위 컴포넌트로 전달(props)

- 전달된 함수를 하위 컴포넌트가 실행(실제 값은 상위 컴포넌트에 저장)

 

1) 부모는 자식한테 자신이 가진 데이터(문자열, 배열, 객체, 함수 등)를 줄 수 있다.

부모에서 useState를 만들고, 자식한테 setValue를 전달한다.

 

2) 자식이 props를 통해 setValue()를 전달받고 실행한다.

props.setValue(10)을 하면 부모에 10이 전달된다.

 

3) 자식에게 데이터를 전달받아 value가 10으로 변경된다.

다른 자식 컴포넌트에게 숫자 10을 props를 통해 전달할 수 있다.

 

App.js

import React, { useState } from "react";
import ChildComponent from "./components/ChildComponent";
import ChildComponent2 from "./components/ChildComponent2";

// 하위 컨포넌트에서 받은 값을 받아서
// 다른 하위 컨포넌트에 전달 할 수 있다

function App() {
  const [value, setValue] = useState("");

  function addDataHandler(data) {
    // data => 자식 컴포넌트가 전달해준 값
    console.log(value); // ""
    setValue(data); // value 값 변경
    console.log(value); // "변경된 값"
  }
  return (
    <>
      <h3>ChildComponent로부터 전달받은 데이터 : {value}</h3>
      <ChildComponent name="soo" age="10" onAddData={addDataHandler} />
      {/* onAddData라는 함수 키가 있고, addDataHandler가 수행된 값이 들어간다.*/}
      <ChildComponent2 text={value} />
    </>
  );
}

export default App;

 

ChildComponent.js

import React from "react";
// 여기서 변하는 값을 상위 컴포넌트에 전달

function ChildComponent(props) {
  // props.name => soo
  // props.age => 10
  // props.onAddData => addDataHandler(data) => data = 글자들...

  function updateValue(e) {
    props.onAddData(e.target.value);
    //이벤트가 발생하는 함수이고 props의 onAddData속성에 입력한 input값을 저장한다
    //e.target : 이벤트가 일어나는 태그 = input
  }

  return (
    <div>
      <h3>
        입력 : <input type="text" onChange={updateValue} />
        {/* 값이 변할때 updateValue 함수 호출 */}
      </h3>
    </div>
  );
}

export default ChildComponent;

 

ChildComponent2.js
import React from "react";

const ChildComponent2 = (props) => {
  // const {text} = props
  // text는 상위 컴포넌트로부터 받은 값이 들어있는 props의 값을 가진다???
  return (
    <div>
      <h3>형제 컴포넌트로부터 전달받은 데이터 : {props.text}</h3>
    </div>
  );
};

export default ChildComponent2;

 

새싹DT 기업연계형 프론트엔드 실무 프로젝트 과정 7주차 블로그 포스팅