본문 바로가기
Programming

React Functional Component props, state state hooks?

by 개발자 염상진 2022. 5. 6.

 

what is props, state, state hook in react and How can I use them?

 

 

리액트 컴포넌트 사이에 데이터 교환을 하기 위한 방법이 필요하다. 리액트에서 사용하는 JSX 문법으로 HTML DOM과 CSS DOM을 만들어내기 때문에 컴포넌트 사이에 개발자가 원하는 데이터 교환은 필수적인 과정이다. 데이터를 교환하고, 저장하면서 동적인 웹 브라우저의 렌더링이 가능하다.

 

리액트에서 컴포넌트 간 데이터 교환을 도와주는 요소는 state와 props 두가지가 있다. 

 

① State : 컴포넌트 내에서만 사용가능한 Private Data

 

② props : 다른 컴포넌트로 넘길 수 있는 Public Data

 

아래 그림으로 살펴보면 외부에서 전달되는 props를 받아서 컴포넌트 내에서 state로 사용한 후 Rendering 하는 과정이다.

 

 

props in React

 

Props는 외부 컴포넌트에서 파라미터로 전달되는 public data다. props를 받은 컴포넌트는 props 자체를 수정할 권한은 없다. 리액트에서 props는 Javascript에서의 매개변수나 HTML에서의 속성과 유사한 성질을 가지고 있다. props를 받은 컴포넌트는 props를 사용해서 동적인 렌더링을 할 수 있다.

 

외부 컴포넌트에서 props를 던질 때는 HTML 속성으로 데이터를 보내게 된다.

 

 

state in React

 

리액트 컴포넌트들은 built-in state 객체를 가지고 있다. State는 private data이기 때문에 다른 컴포넌트에서는 접근자체가 불가능하다. 하지만 매개변수 형식으로 다른 컴포넌트에 변수로써는 넘겨서 사용이 가능하다. 

 

State가 변경될 때 마다 컴포넌트는 render() function을 실행시키고 HTML 에 반영하게 된다. 아래 코드에서 this.state.name을 변경하면 웹 브라우저에서 렌더링 되는 <h1>태그의 value가 변경되는 식이다.

 

State는 기본적으로 dictionary 형태의 데이터 타입을 가지며 다양한 데이터를 한번에 담을 수 있게 된다. state를 변경하는 작업은 clickEvent나 scrollEvent 등 HTML의 이벤트나 리액트 LifeCycle method를 가지고 핸들링이 가능하다. 

 

class HelloWorldComponent extends React.Component{
	constructor(props){
    	super(props);
        this.state = {
        	name : 'hello world';
        }
	}
    
    render(){
    	return <h1>My Name is {this.state.name}</h1>
	}
}

 

 

props vs state in React

 

Props State
다른 컴포넌트로 전달가능하지만 수정은 불가능 컴포넌트에서 이벤트 속성 + LIfe Cycle 으로 변경가능. 
다른 컴포넌트에서 전달됨 컴포넌트 내에서 자식 컴포넌트로 전달가능
Public Data Private Data

 

 

state hooks in React

 

state Hooks의 HOOK 기능은 React 16.8 이후로 적용되었다. 이제 더 이상 클래스 컴포넌트를 사용하지 않아도 함수형 컴포넌트에서도 state를 사용해 컴포넌트간 통신이 가능해진 것이다. 

 

기존 클래스형 컴포넌트를 사용할 때 Javascript 안에서의 this 의미 모호성 때문에 복잡한 코드와 상당한 이해도가 필요했다. 또한 코드의 최소화가 힘들고 핫 리로딩(수정 후 바로 렌더링 해서 보여주는 기능)에서 깨지는 현상이 발생했다. 이러한 문제점으로 facebook에서는 클래스형 컴포넌트를 제거하지는 않지만 함수형 컴포넌트에서 state Hooks를 적용하기로 한다.

 

import React, { useState } from 'react';

function Example() {
  // "count"라는 새 상태 변수를 선언합니다
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

 

useState

 

React Hook은 useState 예약어를 사용한다. useState는 현재의 값을 담은 state와 이를 업데이트하는 함수를 쌍으로 제공된다. 이 함수는 기존 클래스 컴포넌트에서 사용했던 this.setState와 거의 흡사하지만 이전 state와 별개로 데이터를 관리한다는 차이점을 가지고 있다.

 

useState의 매개변수로 받는 값은 초기 state값을 설정하는데 사용된다. 위의 예시에서는 count를 0으로 초기화 하게 된다. 클래스형 컴포넌트와 다르게 state 값은 굳이 객체일 필요가 없다. 다른 타입의 데이터를 담을 수 있게 된다. 또한 하나의 state 뿐만 아니라 여러개의 state를 선언해서 사용이 가능하다.

 

function ExampleWithManyStates() {
  const [age, setAge] = useState(42);
  const [fruit, setFruit] = useState('banana');
  const [todos, setTodos] = useState([{ text: 'Learn Hooks' }]);
  // ...
}

 

 

Effect Hook

 

리액트 16.02 부터 제공하는 Hook 기능은 리액트 Life Cycle을 개선하는 기능을 제공한다. 리액트 클래스형 컴포넌트에서는 componentDidMount, componentDidUpdate, componentWillUnmount 등의 목적을 달성할 수 있는 effect Hook 기능을 제공한다.

 

클래스형 컴포넌트 내에서 리액트는 기본적으로 LifeCycle을 가지고 있다. 최초 컴포넌트가 실행될 때 생성자에서 props 데이터를 받아오고 렌더링을 진행 한후 DOM이 다 만들어지고 난 후 componentDidMount() 메소드를 실행하는 과정을 LifeCycle이라 한다.

 

useEffect

effectHook을 사용해서 DOM을 생성한 후 effect 함수를 실행하게 된다. 기본적으로 Effects는 함수형 컴포넌트 내에 선언되기 때문에 props와 state 데이터에 접근이 간으함. 매번 렌더링을 완료한 뒤 effects를 실행하게 되고, 만약 해제할 필요가 있다 면 따로 해제기능을 가진 함수를 작성해주면 된다. 

 

import React, { useState, useEffect } from 'react';

function Example() {
  const [count, setCount] = useState(0);

  // componentDidMount, componentDidUpdate와 유사함
  useEffect(() => {
    // 브라우저 API를 이용해 문서의 타이틀을 업데이트합니다
    document.title = `You clicked ${count} times`;
  });

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

 

Effects를 해제하는 경우 useEffects에서 해제 기능을 가진 함수를 반환해준다. useState와 유사하게 함수형 컴포넌트 내에서 여러개의 useEffects를 사용할 수 있다. 클래스형 컴포넌트에서 Life Cycle 별로 메소드를 따로 구성해줘야 하는 불편함을 하나의 useEffects를 사용해서 처리할 수 있게 된 것이다. 

 

import React, { useState, useEffect } from 'react';

function FriendStatus(props) {
  const [isOnline, setIsOnline] = useState(null);

  function handleStatusChange(status) {
    setIsOnline(status.isOnline);
  }

  useEffect(() => {
    ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
    return () => {
      ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
    };
  });

  if (isOnline === null) {
    return 'Loading...';
  }
  return isOnline ? 'Online' : 'Offline';
}

 

 

Hook 사용 규칙

 

① 최상위 레벨에서만 Hook을 호출해야 한다. 중첩함수나 반복문 내에서 Hook을 실행해서는 안된다.

 

② React 함수형 컴포넌트 내에서만 Hook을 호출해야 한다. 

 

 

State Hook 사용방법

 

먼저 useState를 import 한다.

 

① 최상위 컴포넌트에서 useState를 선언한다.

 

- viewNotificationCheck를 설정하는 useState을 만든다.

- useState() 를 구현하는 toggleNotification() 를 작성한다.

 

② 하위 컴포넌트로 props를 전달한다.

 

- Sidebar 컴포넌트에 useState(toggleNotification + toggleVal)를 매개변수로 전달한다.

 

③ 하위 컴포넌트에서 props를 받아 구체적인 함수를 작동시킨다.

 

- Sidebar 컴포넌트에서 props를 매개변수로 전달받고 onClick 이벤트 발생시 useState인 toggleNotification을 호출한다. 

 

import React, { useState } from 'react';

const App = () => {
    // state 정의

    const [viewNotificationCheck, setviewNotificationCheck] = useState(false);

    const toggleNotification = (e)=>{setviewNotificationCheck(!e)}
  
  	return (
    	<div className="App">
          <main>
            <Sidebar toggleNotification={toggleNotification} toggleVal={viewNotificationCheck} />
            { viewNotificationCheck ?  <NotificationDisplay/>:<Features />   }
          </main>
        </div>
    )
  }
  
  
const Sidebar = (props) => {
  return (
    <section className="sidebar">
        <FontAwesomeIcon className='far' icon={faCommentDots} onClick={()=>props.toggleNotification(props.toggleVal)}/>
        <FontAwesomeIcon className='far notification__message' icon={faBell} onClick={()=>props.toggleNotification(props.toggleVal)}/>
    </section>
  );
};

 

 

★ 참고문서  : 

 

 

Hook 개요 – React

A JavaScript library for building user interfaces

ko.reactjs.org

 

댓글