[React] Props와 State, Hooks, 이벤트

kim unknown·2022년 6월 9일
1

React

목록 보기
5/7
post-thumbnail

1. Props

Props는 컴포넌트에 값을 전달해줄 때 사용한다. 넘겨줄 수 있는 값은 변수, 배열, 객체, 함수 등 자바스크립트 요소 모두 가능하다.

단, props는 읽기전용으로 값이 변경되어서는 안 된다. props의 값을 변경하고 싶다면, props를 직접적으로 변경하는 것이 아닌 새로운 변수를 선언하여 사용한다. 또한, 데이터는 부모요소에서 자식요소로만 전달이 가능하다.

props는 HTML 속성을 통해 컴포넌트로 전달된다. <컴포넌트명 속성="값" />
사용할 때는 {중괄호}를 사용하며 함수형 컴포넌트에선{props.속성}으로, 클래스형 컴포넌트에선 {this.props.속성}으로 호출된다.

// props 사용법1 - props.속성로 받아오기
function Hi(props) => {
  return <h1>Hello, {props.name}</h1>;
}

// props 사용법2 - {속성}로 받아오기
function Hi({name}) => {
  return <h1>Hello, {name}</h1>;
}

<Hi name="홍길동" />  // name(속성)으로 홍길동이란 값을 전달

⭐ Props는 함수의 매개변수라고 생각하면 좋다.


DOM Element의 속성

  • 기본적인 DOM Element의 속성은 camel case로 작성한다. (단, data- 또는 aria- 로 시작하는 속성은 예외)
  • 예외적으로 class는 className, for는 htmlFor로 기존 HTMl과 달리 작성하는 속성도 있다.
  • HTML에서 checkedvalue는 초기값을 의미하는 것과 달리, 리액트에서는 현재 값을 의미한다. 따라서 초기값을 설정하려면 defaultChecked, defaultValue로 설정해줘야 한다는 점을 유의해야 한다.
    초기값을 checked나 value로 설정해버리는 경우, 값을 변경하려해도 변화가 일어나지 않게 된다.
  • 추가로 React에서만 쓰이는 새로운 속성도 있다.
    key : 리액트가 항목을 안전하게 식별할 수 있도록 배열에 고유성을 부여하기 위함.
    dangerouslySetInnerHTML -> 사용 권장 안 함

2. State

State는 컴포넌트의 현재 저장된 값이며, 변할 수 있는 값이다. 리액트는 값이 변경된 부분을 인지하고 그 부분만 재렌더링한다.

useState : state를 가지는 대상과 그 대상의 state를 변화시키는 함수를 생성

state를 생성할 때는 배열 안에 state 변수와 state 갱신 함수를 할당하고 useState로 초기 값을 설정한다. 또한, useState를 import해줘야 한다.

import { useState } from 'react'
const [state 변수, state 변수를 갱신하는 함수] = useState(초기값)

state는 읽기 전용이다. 따라서 state의 값을 변경할 때는 state 변수를 직접 변경하는 것이 아닌, setState 함수를 호출하여 변경한다.

const [count, setCount] = useState(0);  // 초기값 0
setCount((current) => {  // current : 현재 값
	return current + 1   // 현재 값 + 1
})

state가 Object인 경우, Object 자체가 변경되어야 리액트가 변화를 인지할 수 있다. 때문에 Object를 새로운 Object로 복사한 후, 변경하고 싶은 값을 변경하고 새 Object를 리턴해야 한다.

const [user, setUser] = useState({name: '홍길동', age:20 })
setUser((current) => {
  const newUser = { ...current }  // 기존 Object를 newUser로 복사
  newUser.age = 21 // newUser의 age값만 변경
  return newUser   // newUser 리턴
})

• 리액트 생명주기

리액트의 생명주기는 컴포넌트가 이벤트를 다룰 수 있는 시점을 의미하며, Mount(생성), Update(업데이트), Unmount(제거)로 구성된다.

라이프사이클 메서드
📌 will 메서드 : 어떤 작업을 작동하기 전에 실행
📌 Did 메서드 : 어떤 작업을 작동한 후에 실행

constructor : state 데이터 초기화, 컴포넌트를 새로 만들 때마다 호출되는 클래스 생성 메소드
render : 준비한 UI를 렌더링, 클래스 컴포넌트에서 반드시 구현되어야 하는 메소드
componentDidMount : 컴포넌트가 마운트 된 직후 호출하는 메소드
componentDidUpdate : 컴포넌트의 업데이트 작업이 진행된 직후에 호출되는 메소드
componentWillUnmount : 컴포넌트가 언마운트 되어 제거되기 직전에 호출하는 메소드
getDerivedStateFromProps : props에 있는 값을 state에 넣거나, state r값에 변화를 주는 메소드
shouldComponentUpdate : 컴포넌트가 리렌더링을 해야 할지 말아야 할지를 결정하는 메소드
getSnapshotBeforeUpdate : 컴포넌트 변화를 DOM에 반영하기 바로 직전에 호출하는 메소드
componentDidCatch : 에러가 발생했을 때 애플리케이션이 먹통이 되지 않고, 오류 UI를 보여 줄 수 있게하는 메소드


⭐ 요약
Props는 컴포넌트에 전달하는 값으로, 직접 수정 불가능하다
State는 컴포넌트 내부에서 선언되어 관리되는 값으로, 수정 가능하다.


3. Hooks

Hooks는 컴포넌트에서 데이터를 관리(State)하고 데이터가 변경될 때 상호작용(Effect)을 하기 위해 사용한다. Hooks가 도입됨으로써 함수형 컴포넌트에서도 상태 관리를 할 수 있게 되었다. 클래스 컴포넌트로 구현해야 했던 것들을 함수형 컴포넌트에서 더 간편하게 구현할 수 있게 되었고 그 결과로 함수형 컴포넌트의 사용이 증가했다.

• Hook명은 use로 시작하며 앞서 살펴본 useState도 Hook이다.
• Hook은 React 함수내에서만 사용이 가능하다.
• 최상위 레벨에서만 Hook을 호출할 수 있다. 즉, 가장 바깥쪽 {중괄호}안에서 호출되어야 한다는 것이다. (for문, if문, 콜백함수 등 X)

• useState

useState는 앞서 살펴보았기 때문에 간단하게만 짚고 넘어가도록 하겠다.

  • 컴포넌트의 현재 저장된 값, 동적인 데이터(state)를 관리
  • state를 가지는 대상과 state를 변화하는 함수를 생성하고, state의 초기값을 설정
  • state는 읽기 전용이다.
  • state값을 변경하려면 setState 함수를 이용한다.
  • state가 변경되면 자동으로 컴포넌트가 재 렌더링된다.

useState를 호출하면 배열이 반환된다. 그 첫번째 인덱스는 state이름, 두번째 인덱스는 setState 이름이다. 따라서 useState를 사용하려면 배열에 두 가지를 선언해야 한다.
import { useState } from 'react'
const [state이름, setState이름] = useState(초기값)

const App = () => {
  const [name, setName] = useState("홍길동")
  setName("신짱구")
}

• useEffect

useEffect를 사용하면 함수 컴포넌트에서 side effect를 수행할 수 있다. (특정 부분이 바뀔 때마다 부수적으로 다른 부분도 함께 변화되는 효과)

import { useEffect } from 'react'
useEffect(실행될 콜백 함수, [변화를 감지할 대상(state/props)])

  • useEffect는 컴포넌트가 최초로 렌더링될 때 실행 된다. 즉, 무조건 한 번씩은 실행된다는 의미이다.
  • 변화를 감지할 대상으로 지정한 State나 Prop가 변경될 때마다 이펙트 콜백 함수가 실행된다.
  • 대상을 지정해주지 않으면 발생하는 모든 변화에 반응한다.
  • 감지 대상은 여러 개 지정할 수 있다. [감지 대상1, 감지 대상2, ...]
  • 최초 렌더링 시에만 실행하도록 하고 싶다면 감지 대상에 [빈배열]을 넘겨주면 된다.
import React, {useState, useEffect} from "react";

const App = () => {
    const [name, setName] = useState("신짱구");
  
  	// name을 수정할 때마다 console을 찍음
    useEffect(() => {
    	console.log(`이름이 ${name}으로 변경 되었습니다.`)
  	}, [name])
  
  // input에 입력된 값으로 내용 변경
  return (
    <div>
      <input onChange={
          (event) => setName(event.target.value)
      } value={name} />
      <p>{name}님 안녕하세요.</p>
    </div>
  )
}

• useMemo

useMemo를 사용하면 함수형 컴포넌트 내부에서 발생하는 연산을 최적화할 수 있다.
지정한 대상인 State나 Props가 변경될 경우 해당 값을 활용해 계산된 값을 메모이제이션하여 재렌더링 시 불필요한 연산을 줄인다. 사용하는 형태는 useEffect와 비슷하다.

import { useMemo } from 'react'
useMemo(실행될 콜백 함수, [변화를 감지할 대상(state/props)])

• useCallback

useCallback은 useMemo와 비슷하다. 함수를 메모이제이션하기 위해 사용한다. 컴포넌트가 재렌더링될 때 불필요하게 함수가 재생성되는 것을 방지하기 때문에 주로 렌더링 성능을 최적화해야 할 때 사용한다.

import { useCallback } from 'react'
useCallback(실행될 콜백 함수, [변화를 감지할 대상(state/props)])

❗따라서
useMemo(() => 콜백 함수, 감지 대상)
useCallback(콜백 함수, 감지 대상) 는 같다.

• useRef

useRef는 함수형 컴포넌트에서 ref를 쉽게 사용할 수 있게 해준다. 컴포넌트 생애 주기 내에서 유지할 ref 객체를 반환하며, ref 객체는 .current라는 프로퍼티를 가진다. ref 객체가 변경되어도 컴포넌트가 재렌더링되지 않는다.

import { useRef } from 'react'
useRef(initialValue)


4. Event

• 리액트에서의 이벤트는 camel case로 작성한다.
• 자체적으로 생성한 컴포넌트에는 이벤트를 적용할 수 없으며, DOM 요소(<div>, <p>, <input> 등)에만 이벤트를 적용할 수 있다.
• 이벤트 핸들링은 함수의 형태로 넘겨준다. 따라서, 자바스크립트이기 때문에 {중괄호}에 담아서 전달한다.
• 이벤트가 발생한 요소는 event.target으로, 그 요소의 값은 event.target.value로 받아온다.


• Dom Event

리액트에서의 이벤트는 자바스크립트와 비슷하지만 역시 camel case로 작성하기 때문에 이벤트명들이 약간의 차이가 있다. 자주 사용되는 이벤트는 다음과 같다.

onClick : 요소가 클릭되었을 때
onDoubleClick : 요소를 더블 클릭했을 때
onKeyDown, onKeyUp, onKeyPress: 키보드 입력이 발생했을 때
onChange : 요소의 값이 변경되었을 때
onFocus : 요소에 포커스가 이동되었을 때
onBlur : 요소에 포커스가 벗어났을 때
onSubmit : Form 요소에서 Submit되었을 때


React에서 이벤트를 처리하는 방법은 두 가지가 있다.

① 익명 함수로 처리하기 onClick={() => {이벤트 내용}}

const App = () => {
  return (
    <div>
      <button onClick={() => {
        alert('클릭!');
      }}>Click!!</button>
    </div>
  )
}

② 핸들링 함수 선언하기 onClick={이벤트핸들링함수명}

const App = () => {
  const clickEvent = () => {
  	alert("클릭!");
  }
  return (
    <div>
    	<button onClick={clickEvent}>Click!!</button>
    </div>
  );
};

이벤트에 state와 event.target 적용해보기

import React, {useState} from 'react';

function App() {
  // state 생성
  // name(state 변수), setName(이름 변경 함수), useState(초기값은 홍길동)
  const [name, setName] = useState("홍길동");
  
  // 이벤트 핸들링 함수
  // 이벤트가 발생한 요소에서 입력된 값(이름)을 가져오고 해당 값으로 name 변경(setState)
  function handleInput(event) {
	setName(event.target.value)
  }
	
  return (
    // input의 값이 변경되었을 때 handleInput 이벤트 핸들링
    // 기본값으로 name 설정, 출력값은 <이름>님 반갑습니다.
    <div className="App">
      <input onChange={handleInput} defaultValue={name} />
	  <span>{name}님 반갑습니다.</span>
    </div>
  );
}

참고자료
🐰 엘리스 SW 엔지니어 트랙 2기
📑 React 공식 문서
📑 컴포넌트 생명주기 메서드
📑 리액트의 Hooks 완벽 정복하기

0개의 댓글