본문 바로가기
📌 Front End/└ React

[React] 리액트 이벤트 처리 - 핸들러, 컴포넌트 상태(useState), 단방향 바인딩

by 쫄리_ 2024. 8. 26.
728x90
반응형

📌 이벤트 핸들링 / 이벤트 핸들러

  • 이벤트 핸들링 : 이벤트가 발생하면 특정 코드가 동작하도록 만드는 작업
  • 이벤트 핸들러 : 이벤트를 처리하는 함수 
    (onClick, onSubmit 등과 같은 이벤트 프로퍼티에 함수 형태로 전달)

📌 이벤트 핸들러 (단방향 데이터 흐름)

컴포넌트에서 특정 DOM 요소에 이벤트가 동작하도록 하려면,

해당 DOM 요소에 이벤트 핸들러를 설정해야 합니다.

HTML 엘리먼트의 이벤트는 JSX내에서 'on + 이벤트명' 형태의 프로퍼티로 제공된다.

예를 들어, 클릭 이벤트는 onClick으로 설정합니다.

 

리액트에서 데이터는 부모 컴포넌트에서 자식 컴포넌트로 단방향으로 흐릅니다. 

이벤트 핸들러도 동일한 원칙에 따라 작동하며, 

부모 컴포넌트는 자식 컴포넌트에 이벤트 핸들러 함수를 전달하고,

자식 컴포넌트는 이 함수를 특정 DOM 요소에 바인딩하여 사용합니다.

 

  • 이벤트명 카멜(Camel) 표기법 
    ➡️ onClick, onSubmit, ...

  • JSX에 문자열 대신 {함수} 전달
    ➡️ <button onClick={onClickName}>
    ➡️ <Component onClick={handleClick}/>

  • DOM 요소에만 이벤트 설정 가능
    ➡️ 설정 가능 ⭕ : <div>, <button>, <input>, <form>, <span>
    ➡️ 설정 불가 ❌ : 사용자 정의 컴포넌트 (예: <MyComponent>) 

JSX DOM 이벤트 프로퍼티 이벤트 호출 시점
onClick 엘리먼트에 마우스나 키보드가 클릭 된 경우
onChange 엘리먼트의 내용이 변경된 경우
onSubmit 폼의 데이터가 전송될 때
onKeyDown 키보드 버튼이 눌린 경우
(값 입력전에 발생하며, shift, alt, ctrl 등 특수키에 동작한다.)
(한/영, 한자 등은 인식불가)
onKeyUp 키보드 버튼이 눌렸다 뗀 경우
(값 입력후에 발생하며, onKeyDown 과 동일하게 동작한다.)
onKeyPress 키보드 버튼이 눌려져 있는 경우
(실제 글자가 작성될때 이벤트이며,
ASCII 값으로 사용되어 특수키를 인식 못한다.)
onFocus 엘리먼트가 포커스 된 경우
onBlur 엘리먼트가 포커스가 사라진 경우
onMouseMove 엘리먼트 위에서 마우스 커서가 움직일 때
onMouseDown 마우스 버튼이 클릭되기 시작할 때
onMouseUp 마우스 버튼 클릭이 끝날 때

📝 React 이벤트 핸들러 문법

on 접두사가 붙은 경우, 이는 리액트의 JSX에서 실제 DOM 이벤트에 연결된 프로퍼티임을 의미합니다.

예를 들어, onClick은 클릭 이벤트와 연결된 프로퍼티입니다.

이때 이벤트 핸들러는 이벤트를 실행할 코드를 직접 전달하는 것이 아니라, 함수의 형태로 전달합니다. 

예를 들어, onClick={handleEvent}는 클릭 이벤트가 발생했을 때 handleEvent 함수를 호출하게 됩니다.

handle 접두사가 붙은 이름은 일반적으로 이벤트가 발생했을 때 호출되는 함수임을 나타냅니다. 

예를 들어, handleEvent는 이벤트 발생 시 실행될 함수를 의미합니다.

onClick = {함수명}
// onClick은 클릭 이벤트와 연결된 프로퍼티, handleEvent는 클릭 이벤트 발생 시 호출될 함수
<button onClick={handleEvent}>Event</button>

 


사용예시

🔎 JSX에서 버튼 클릭 이벤트 처리

JSX에서 버튼 클릭 이벤트를 처리하려면 onClick 속성을 사용한다. onClick 속성에는 클릭 시 실행할 함수를 지정한다.

코드에서 handleClick은 버튼 클릭 시 실행될 함수이다.
함수는 미리 정의해두거나 onClick 속성 내에서 직접 정의할 수 있다.

여기서 onClick 이벤트는 DOM 요소인 button에 직접 설정된 것입니다.

button을 클릭하면 handleClick 함수가 실행돼서 콘솔에 "버튼 클릭!" 출력돼요.

 

🏷️ 핸들링함수 선언

별도의 핸들링 함수를 선언하고 Element에 넘겨주는 방법

함수는 컴포넌트 내부에 미리 정의해두고, onClick 속성에 함수 이름을 전달합니다.

  • 장점 : 함수가 컴포넌트의 다른 부분에서 재사용될 수 있고, 코드가 더 깔끔하고 읽기 쉽다.
  • 단점 : 함수가 별도로 정의되어야 하며, 이로 인해 코드의 길이가 길어질 수 있습니다.
function App() {
  function handleClick() {
    console.log("버튼 클릭!");
  }

  return <button onClick={handleClick}>클릭</button>;
}

 

🏷️ 익명함수 처리

 

이벤트를 할당하는 부분에서 익명 함수를 작성하는 방법

  • 장점 : 코드가 간결, 핸들링 함수가 이벤트 핸들러에 직접 정의되므로 코드가 짧고 직관적
  • 단점 : 익명 함수는 매 렌더링마다 새로 생성되므로, 성능에 영향을 줄 수 있으며, 디버깅이 어렵다.
function App() {
  return <button onClick={() => console.log("버튼 클릭!")}>클릭</button>;
}

 


📝 사용자 컴포넌트에는 이벤트 불가능

  • DOM 요소 : div, button, input, form, span 등과 같은 기본 HTML 요소에는 직접 이벤트 설정가능
  • 리액트 컴포넌트
    리액트 컴포넌트에는 이벤트를 직접 설정할 수 없지만
    컴포넌트에 이벤트 핸들러를 props로 전달하고, 
    컴포넌트 내부에서 이를 DOM 요소에 연결하여 이벤트를 처리할 수 있습니다.

 

<Component>라는 리액트 컴포넌트에는 onClick을 달아서 의도한대로 이벤트가 실행되지 않고,

그냥 color, name과 같은 props를 전달해주는 것에 불과하다.

function App() {
  const sayHi = function () {
    alert('hello');
  }
  return (
    <>
      <Component onClick={sayHi} name="권소현" nickname="토끼" />
    </>
  );
}

 

 

🔎 리액트 컴포넌트에 이벤트 핸들러 전달 및 설정

App 컴포넌트가 sayHi 함수를 onClick prop으로 Component 컴포넌트에 전달합니다.

Component 컴포넌트는 이 onClick prop을 button 요소에 설정하여 버튼 클릭 시 sayHi 함수가 호출되도록 합니다.

function App() {
  const sayHi = () => {
    alert('hello');
  };

  return (
    <Component onClick={sayHi} name="권소현" nickname="토끼" />
  );
}

function Component(props) {
  return (
    <div>
      <p>Name: {props.name}</p>
      <p>Nickname: {props.nickname}</p>
      <button onClick={props.onClick}>Click me</button>
    </div>
  );
}

 


사용예시

 

🔎 이벤트 핸들러가 작동하지 않는 경우

  • 화면 표시 : 권소현 / 토끼 / Click me 버튼
  • 버튼 클릭 시 : 버튼 클릭 시 아무 동작도 발생하지 않음

onClick={props.onClick}이 Component 컴포넌트 내부의 div 요소에 설정되어 있습니다.

이 경우, div 요소에 클릭 이벤트 핸들러가 설정되어 있지만, div 요소는 스타일상 클릭 가능한 요소가 아닐 수 있으며,

div 요소는 사용자와의 상호작용을 고려할 때 일반적으로 클릭 가능한 영역으로 사용되지 않습니다.

function App() {
  const sayHi = function () {
    alert('hello');
  };

  return (
    <>
      <Component onClick={sayHi} name="권소현" nickname="토끼" />
    </>
  );
}

function Component(props) {
  return (
    <div>
      <p>Name: {props.name}</p>
      <p>Nickname: {props.nickname}</p>
      {/* onClick 이벤트 핸들러가 div 요소에 설정됨 */}
      <div onClick={props.onClick}>Click me</div>
    </div>
  );
}

 

🔎 이벤트 핸들러가 작동하는 경우

  • 화면 표시 : 권소현 / 토끼 / Click me 버튼
  • 버튼 클릭 시 : 클릭 시 경고 창이 나타나고, 그 안에 "hello"라는 메시지가 표시됨

onClick={props.onClick}이 button 요소에 설정되어 있습니다.

사용자가 버튼을 클릭하면, sayHi 함수가 호출되어 경고 창이 표시됩니다.

이 경우 이벤트 핸들러가 button 요소에 올바르게 설정되었으므로,

사용자의 클릭에 반응하여 지정된 동작이 정상적으로 수행됩니다.

function App() {
  const sayHi = function () {
    alert('hello');
  };

  return (
    <>
      <Component onClick={sayHi} name="권소현" nickname="토끼" />
    </>
  );
}

function Component(props) {
  return (
    <div>
      <p>Name: {props.name}</p>
      <p>Nickname: {props.nickname}</p>
      {/* onClick 이벤트 핸들러가 button 요소에 설정됨 */}
      <button onClick={props.onClick}>Click me</button>
    </div>
  );
}

 


💡 사용자 컴포넌트에서 이벤트 처리

리액트에서 사용자 정의 컴포넌트(MyComponent)에서 이벤트를 처리하려면,

컴포넌트 내부에서 이벤트 핸들러를 DOM 요소에 직접 연결해야 합니다.

사용자 정의 컴포넌트는 이벤트 핸들러를 props로 받아서 내부의 DOM 요소에 전달함으로써 이벤트를 처리할 수 있습니다.

 

  • MyComponent
    • props.onClickdiv 요소의 onClick 이벤트 핸들러로 설정됩니다.
    • 이렇게 하면 div를 클릭할 때 props.onClick에서 전달된 함수가 호출됩니다.
  • App
    • App 컴포넌트는 MyComponent를 렌더링하면서 onClick prop에 클릭 시
    • 콘솔에 "Component clicked!"를 출력하는 함수를 전달합니다.

 

함수 전달 : App에서 MyComponent에 onClick prop으로 함수를 전달합니다.
props : MyComponent에서 props.onClick을 통해 전달된 함수를 사용할 수 있습니다.
이벤트 핸들러 설정 : MyComponent는 이 함수를 div 요소의 클릭 이벤트에 연결하여 사용합니다.

 

function MyComponent(props) {
    return <div onClick={props.onClick}>I'm a component!</div>;
}

function App() {
    return <MyComponent onClick={() => console.log("Component clicked!")} />;
}

 


SyntheticEvent와 이벤트 객체

리액트에서는 브라우저의 기본 이벤트 객체를 래핑하는 SyntheticEvent 객체를 사용합니다.

이 객체는 다음과 같은 속성과 메서드를 제공하여 이벤트 처리와 관련된 다양한 작업을 가능하게 합니다.

 

🔎 SyntheticEvent의 주요 속성과 메서드

  • 속성
    • type : 이벤트의 유형을 나타냅니다. 
      (예: "click", "change", "keypress" 등)
    • target : 이벤트가 발생한 요소를 가리킵니다. 
      이 속성은 이벤트가 발생한 DOM 요소를 참조
    • currentTarget : 이벤트 리스너가 등록된 요소를 가리킵니다. (이벤트 핸들러 실행)
      target과는 달리 이벤트 핸들러가 실행되고 있는 요소를 참조
  • 메서드
    • preventDefault() : 이벤트의 기본 동작을 막습니다. 
      예를 들어, 링크 클릭 시 페이지 이동을 막거나 폼 제출을 방지할 때 사용
    • stopPropagation() : 이벤트의 전파를 막습니다. 
      자식 요소에서 발생한 이벤트가 상위 요소로 전파되지 않도록 합니다.
  • e.nativeEvent
    • 리액트의 SyntheticEvent 객체를 통해 접근할 수 있는 브라우저의 원래 이벤트 객체입니다. 
      이를 통해 브라우저의 기본 이벤트 속성이나 메서드에 접근할 수 있습니다.

🔎 기본 이벤트 객체 사용 예시

● SyntheticEvent 는 리액트가 사용하는 이벤트 객체로, 브라우저 이벤트를 감싸고 다양한 속성과 메서드를 제공합니다.

e.nativeEvent 는 실제 브라우저의 원래 이벤트 객체를 참조할 수 있게 해줍니다.

preventDefault() stopPropagation() 메서드를 사용하여 이벤트의 기본 동작과 전파를 제어할 수 있습니다.

function App() {
  const handleClick = (event) => {
    console.log(event); 				// SyntheticEvent 객체 콘솔 출력
    console.log('Event type:', event.type);		// 이벤트 타입 출력
    console.log('Event target:', event.target);		// 이벤트 발생 요소 출력
    console.log('Native event:', event.nativeEvent);	// 원래 브라우저 이벤트 객체 출력
    event.preventDefault();				// 기본 동작 방지
    event.stopPropagation();				// 이벤트 전파 방지
  };

  return (
    <div>
      <button onClick={handleClick}>클릭하세요</button>
    </div>
  );
}

 


리액트 이벤트 속성

속성 설명
e.nativeEvent React의 이벤트 객체 안에 포함된 브라우저의 원래 이벤트 객체
e.stopPropagation 이벤트가 상위 요소로 전파되는 것을 막습니다. (이벤트 버블링 제어)
React는 단방향 데이터 흐름을 선호합니다.

이벤트 버블링

속성 설명
e.target 실제로 이벤트가 발생한 요소
e.currentTarget 이벤트 핸들러가 등록된 요소

리액트 이벤트 처리 / 상태관리

상태를 통한 UI 업데이트 상태 관리 리액트에서는 useState 훅을 사용하여 상태를 관리합니다.
상태를 사용하여 UI를 업데이트하고,
직접 DOM을 수정하지 않습니다.
장점 상태를 사용하면
리액트의 가상 DOM 덕분에 성능이 더 좋아지고,
코드가 일관되며 유지보수가 쉬워집니다.
이벤트 처리 루트 요소에서 처리 리액트는 이벤트를 가상 DOM에서 처리하고,
실제 DOM에는 직접 리스너를 추가하지 않습니다.
모든 이벤트는 루트 요소에서 처리됩니다.

예를 들어, <div id="reactRoot"></div>는
리액트가 이벤트를 처리하는 루트 요소가 될 수 있습니다.
이벤트 전파 이벤트는 상위 요소에서 하위 요소로 전달됩니다.
상위 요소에서 이벤트를 관리하고,
하위 요소에서 필요한 경우 처리할 수 있습니다.
이벤트 객체 e.nativeEvent 리액트의 이벤트 객체를 사용하여
원래 브라우저의 이벤트를 확인할 수 있습니다.
이를 통해 실제 브라우저 이벤트에 접근할 수 있습니다.
이벤트 전파 제어 e.stopPropagation()을 사용하여
이벤트의 상위 요소로의 전파를 막을 수 있습니다.
이는 이벤트 버블링을 방지하는 데 유용합니다.

 


🔎 상태를 통한 UI 업데이트

import React, { useState } from 'react';

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

  const handleClick = () => {
    setCount(count + 1); 	// 상태를 업데이트하여 UI를 다시 렌더링
  };

  return (
    <div>
      <p>클릭 횟수: {count}</p>
      <button onClick={handleClick}>클릭하세요</button>
    </div>
  );
}

export default App;

 

🔎 이벤트 객체 사용

import React from 'react';

function App() {
  const handleClick = (e) => {
    console.log('SyntheticEvent:', e); 		// SyntheticEvent 객체 콘솔 출력
    console.log('NativeEvent:', e.nativeEvent); // 실제 브라우저 이벤트 객체 콘솔 출력
    e.stopPropagation(); 			// 이벤트 전파를 멈춤
  };

  return (
    <div>
      <button onClick={handleClick}>클릭하세요</button>
    </div>
  );
}

export default App;

 


📌 useState 컴포넌트 상태 (단방향 데이터 흐름)

함수형 컴포넌트는 useState 훅을 통해 상태를 관리하며, this를 사용하지 않습니다.
이벤트 핸들러에서 콜백 함수는 함수형 컴포넌트의 스코프 내에서 직접 정의되므로 

this와 관련된 문제를 신경 쓸 필요가 없습니다.
함수형 컴포넌트 내의 함수는 const로 선언하여 불변성을 유지하며, this 바인딩이 필요 없습니다.

 

  • 상태 관리
    리액트에서는 useState 훅을 사용하여 컴포넌트의 상태를 관리합니다. 
    this를 사용하지 않고, 상태를 직접 업데이트합니다.
    const [count, setCount] = useState(0);

  • 이벤트 핸들러
    이벤트 핸들러는 컴포넌트 안에서 직접 작성되며, 
    this 문제를 걱정할 필요가 없습니다.
    이벤트 핸들러 함수는 const 로 선언하여 불변성을 유지
    const handleClick = () => setCount(count + 1);   // 이벤트 핸들러는 const로 선언됨

  • 상태(state)
    상태는 컴포넌트 내부에서 동적인 데이터를 저장하고 변경할 때 사용합니다. 
    이벤트와 함께 UI를 업데이트하는 데 유용합니다.
    const [count, setCount] = useState(0);   // useState 훅을 사용하여 count 상태 관리

  • 프로퍼티(props)
    props는 부모 컴포넌트에서 자식 컴포넌트로 전달되는 값
    자식 컴포넌트 내부에서는 props 값을 변경할 수 없습니다. 
    자식 컴포넌트는 props를 읽기 전용으로 사용합니다.
    값이 변경되어야 하는 경우, 
    부모 컴포넌트에서 useState 훅을 사용하여 상태를 관리하고, 
    이 상태를 자식 컴포넌트에 전달합니다.
    function Child(props) {
      return <p>{props.message}</p>;   // props로 전달된 message를 출력
    }

사용예시

  • 부모 컴포넌트 (Parent)
    • useState 훅을 사용해 message 상태를 관리합니다.
    • updateMessage 함수를 통해 상태를 변경합니다.
    • 상태 message를 자식 컴포넌트 Child에 props로 전달합니다.
  • 자식 컴포넌트 (Child)
    • 부모 컴포넌트로부터 전달받은 props.message를 화면에 출력합니다.
    • 자식 컴포넌트는 전달받은 props를 변경할 수 없으며, 단순히 값을 표시합니다.
// ▶ 자식 컴포넌트
function Child(props) {
  return <p>{props.message}</p>;			// 부모 컴포넌트에서 전달된 message를 출력
}

// ▶ 부모 컴포넌트
import React, { useState } from 'react';

function Parent() {
  const [message, setMessage] = useState('안녕하세요!');	// 상태를 사용하여 message를 관리

  const updateMessage = () => {
    setMessage('안녕히 가세요!');			// 버튼 클릭 시 상태를 변경하는 함수
  };

  return (
    <div>
      <h1>부모 컴포넌트</h1>
      <Child message={message} />				{/* 최신 상태값이 자식 컴포넌트에 전달 */}
      <button onClick={updateMessage}>메시지 변경</button>	{/* 상태를 변경하는 버튼 */}
    </div>
  );
}

export default Parent;

 


🧐 State vs Prop

  State Prop
특징 일반 자바스크립트 객체
컴포넌트 내부 선언, 
내부에서 값 변경 (저장)
부모 컴포넌트에서 
자식 컴포넌트에 데이터 전달
앱의 유동적 데이터 다루는 객체 한 번 설정되면 변경 X
이벤트 핸들러는 
일반적으로 state 를 업데이트
상위 컴포넌트는 
하위 컴포넌트에 대한 props 설정

 


📝 State 선언 및 변경 방법

state의 값은 직접 변경하면 안 됩니다.

왜냐하면 이후 호출되는 setState()가 이전에 적용된 변경 사항을 덮어쓰기 때문입니다.
state 값은 기본적으로 불변적(Immutable)인 데이터로 취급하고, 

state의 값을 변경할때는 무조건 setState()를 이용해 state의 값을 변경해야 합니다.
즉, state는 👉 컴포넌트가 가지고 있는 데이터 입니다.

 

 

State 선언 방법

  • const [state, setState] = useState(initialState);
  • React에서는 useState 훅을 사용하여 컴포넌트의 상태를 선언합니다.
  • useState는 두 가지 값을 반환합니다. 현재 상태 값상태를 업데이트하는 함수입니다.
  • 여기서 state는 현재 데이터 값을 나타내고, setState는 상태를 업데이트하는 함수입니다.

State 값 변경

  • setState(newStateValue);   // 상태를 업데이트하여 리렌더링 발생
  • 직접 변경하지 말고, 상태를 변경할 때는 항상 setState 함수를 사용해야 합니다.
  • 상태는 불변(Immutable)으로 취급되며, 직접 변경하지 않고 setState를 통해 변경해야 합니다.
const [현재데이터값, 데이터변경함수] = useState<타입>(초기값);
const [state, setState] = useState(initialState);
// ✔️ set 함수를 통해 상태를 변경해야 리렌더링이 발생합니다.
setState(state + 1);

 

사용예시

  • 📜 app.tsx : 할 일 목록을 관리하고, 버튼 클릭 시 새로운 할 일을 목록에 추가
  • 📜 todo.tsx : 각 할 일 항목을 표시하는 역할

// ▶ app.tsx
import React, { useState } from "react";
import Todo from './todo';

export default function App() {
    // useState를 사용하여 todoList라는 상태 변수를 선언합니다.
    // todoList는 배열이며, 각 항목은 {index, title} 형태입니다.
    let [todoList, todoListChanger] = useState<{index:number, title:string}[]>([]);

    return (
        <div>
            {/* 버튼을 클릭하면 새로운 할 일 항목이 추가됩니다. */}
            <button onClick={() => {
                // [...todoList]는 현재 todoList의 모든 항목을 새로운 배열로 복사합니다.
                // {index: todoList.length, title:"제목"}는 새로운 할 일 항목입니다.
                // 이 새로운 항목을 포함한 새로운 배열을 생성하여 상태를 업데이트합니다.
                todoListChanger([...todoList, {index: todoList.length, title:"제목"}]);
            }}>
                추가
            </button>
            {/* todoList의 각 항목을 Todo 컴포넌트를 사용하여 화면에 표시합니다. */}
            <ol>
                {todoList.map((item, index) => (
                    <li key={index}>
                        <Todo todo={item} />
                    </li>
                ))}
            </ol>
        </div>
    );
}
// ▶ todo.tsx
import React from "react";

// Props 타입 정의
interface Props {
    todo: {
        index: number,
        title: string
    }
}

export default function Todo({ todo }: Props) {
    const { index, title } = todo;	// todo 객체를 분해하여 index와 title을 추출
    
    return (
        <div>
            {/* 할 일 항목의 인덱스와 제목을 표시합니다. */}
            <span style={{ display: "inline-block", width: 50 }}>{index}</span>
            <span style={{ width: 200 }}>{title}</span>
        </div>
    );
}

 


사용예시

🔎 DOM Input 값을 State에 저장

  • 상태 선언
    • inputValue라는 상태 변수를 useState 훅을 사용해 선언합니다. 
      이 상태는 input 필드의 값을 저장합니다.
  • 상태 업데이트 함수
    • handleChange 함수는 input 필드의 값이 변경될 때마다 호출됩니다. 
      이 함수는 이벤트 객체에서 target.value를 읽어와 inputValue 상태를 업데이트합니다.
  • 컴포넌트 렌더링
    • input 요소의 value 속성에 inputValue 상태를 할당하여 input 필드의 값을 제어합니다.
    • onChange 이벤트 핸들러로 handleChange 함수를 설정하여 입력 값이 변경될 때마다 상태를 업데이트합니다.
    • inputValue 상태의 값을 <span> 태그를 통해 화면에 표시합니다.
import { useState } from "react";

function App() {
  // ▶ input에 입력한 값을 보관할 State를 생성하기
  // → inputValue: 현재 입력 필드 값
  // → setInputValue: 상태와 상태 업데이트 함수 정의
  const [inputValue, setInputValue] = useState("");
  
  // ▶ 입력 값이 변경될 때마다 상태를 업데이트하는 함수
  function handleChange(event) {
    setInputValue(event.target.value);
  }
  
  return (
    <div>
      {/* input 필드와 상태를 연결 */}
      <input
          value={inputValue}		// 상태 값으로 input 필드의 값 설정
          onChange={handleChange}	// 입력 값이 변경될 때 상태를 업데이트하는 함수
      />
      {/* 상태 값을 화면에 표시 */}
      <span>{inputValue}</span>
    </div>
  );
}

 


🔎 컴포넌트간 이벤트 전달

🌀 자식 ➡️ 부모 (상향식 전달)

부모와 자식 컴포넌트 간의 이벤트 전달 및 상태 관리

 

  • Myform 컴포넌트 (자식)
    이 컴포넌트는 입력 필드 <input> 를 반환합니다.
    부모 컴포넌트로부터 전달받은 onChange 함수를 이벤트 핸들러로 설정하여, 
    입력 필드의 값이 변경될 때마다 onChange 함수가 호출됩니다.

  • App 컴포넌트 (부모)
    이 컴포넌트는 상태를 관리합니다.
    Myform 컴포넌트를 포함하고 있으며, Myform에 onChange 이벤트 핸들러를 전달합니다.
    onChange 핸들러는 입력 필드의 값이 변경될 때 호출되며, 
    username 상태를 업데이트합니다.
// ▶ Myform 컴포넌트
import React from 'react';

function Myform({ onChange }) {
  // 부모 컴포넌트로부터 받은 onChange 함수 설정
  return <input onChange={onChange} />;		// 입력 필드의 값이 변경될 때 onChange 함수 호출
}

export default Myform;
// ▶ App 컴포넌트
import React, { useState } from 'react';
import Myform from './Myform';

function App() {
  const [username, setUsername] = useState("");	// 상태를 정의하고 초기값을 빈 문자열로 설정

  return (
    <div className="App">
      <h1>{username}님 환영합니다.</h1>
      <Myform
        onChange={(event) => {
          setUsername(event.target.value);	// 입력 값이 변경될 때마다 username 상태 업데이트
        }}
      />
    </div>
  );
}

export default App;


🔎 커스텀 훅을 이용한 상태 관리

🌀 자식 ➡️ 부모 (상향식 전달)

부모와 자식 컴포넌트 간의 이벤트 전달 및 상태 관리

커스텀 훅은 상태 관리와 같은 로직을 재사용할 수 있게 해주는 특별한 함수입니다.

컴포넌트에서 복잡한 상태 관리 로직을 직접 작성하는 대신,

이 로직을 훅으로 분리하여 여러 컴포넌트에서 재사용할 수 있습니다.

 

  • 커스텀 훅
    상태와 상태를 업데이트하는 로직을 추상화합니다. 
    이 훅은 상태와 이를 변경할 수 있는 함수를 제공하여, 
    상태 관리 로직을 여러 컴포넌트에서 재사용할 수 있게 합니다.

  • 부모 컴포넌트
    커스텀 훅을 호출하여 상태와 상태를 업데이트하는 함수를 얻고, 
    이를 자식 컴포넌트에 전달합니다.

  • 자식 컴포넌트
    부모로부터 전달받은 상태와 상태 업데이트 함수를 사용하여 입력 필드의 값을 표시하고, 
    값이 변경될 때 상태 업데이트 함수가 호출되어 
    부모 컴포넌트의 상태가 변경되도록 합니다.
import React from 'react';

// ---------------------------------------------------------------------
// ▶ 커스텀 훅 (useTwoWayBinding)
// → 상태와 상태를 업데이트하는 함수
function useTwoWayBinding(initialValue) {
	// initialValue: 처음 상태의 값 (예: 빈 문자열 "")
	const [value, setValue] = React.useState(initialValue);
    
	// 입력값이 변경되면 호출되는 함수
	const handleChange = (e) => {
		setValue(e.target.value);
	};
    
	// 상태와 상태를 업데이트하는 함수를 반환
	return [value, handleChange];
}

// ---------------------------------------------------------------------
// ▶ 부모 컴포넌트 (ParentComponent)
// → 상태와 상태를 업데이트하는 함수를 사용하기 위해 커스텀 훅을 호출
import useTwoWayBinding from './useTwoWayBinding';

function ParentComponent() {
	// 커스텀 훅을 사용하여 상태와 상태를 업데이트하는 함수를 얻습니다.
	// → useTwoWayBinding 훅을 호출하여 상태(inputValue)와 
	//   상태를 업데이트하는 함수(setInputValue)를 얻습니다.
	const [inputValue, setInputValue] = useTwoWayBinding('');

	return (
		// ChildComponent에 value와 onChange라는 props로 전달
		<ChildComponent value={inputValue} onChange={setInputValue} />
	);
}

// ---------------------------------------------------------------------
// ▶ 자식 컴포넌트 (ChildComponent)
// → 부모로부터 받은 value와 onChange를 사용
function ChildComponent({ value, onChange }) {
	// ChildComponent는 value와 onChange를 props로 받습니다.
	return <input type="text" value={value} onChange={onChange} />;
}

 


728x90
반응형