Handling Events 와 Conditional Rendering

‍박태우·2024년 10월 4일

React Study

목록 보기
4/4

1. Handling Evnets

컴퓨터의 이벤트 == 사건
이벤트 핸들링 == 이벤트를 처리한다.


1. DOM 의 이벤트

DOM 에서 클릭 이벤트를 처리하는 예제로서 클릭 시 activate() 함수가 실행된다.

2. 리액트의 이벤트

앞선 코드와 동일한 기능 또한 camel 표기법으로 onClick으로 되며, 함수명을 이용하여 이벤트를 처리한다.

3. Event Handler

개념 : 이벤트 발생 시 해당 이벤트를 처리하는 함수
이벤트가 발생하면 계속 듣고 있는다는 의미로 Event Listener 라고 부르기도 함

  • 예시 (클래스 컴포넌트)

isToggledOn 이라는 state 가 존재한다. 버튼 클릭 시 handleClick 함수가 호출된다.
구현한 함수를 생성자(constructor) 에서 bind 를 이용하여 대입해준다.

  • bind 하는 이유 : 기본적으로 자바스크립트에서는 클래스 함수들이 바운드 되지 않기 때문에 따로 bind 가 필요하다.
    (바운드를 하지 않으면 this.handleClick 은 글로벌스코프에서 호출되는데 이렇게되면 undefined 가 된다.)

=> 이는 자바스크립트의 공용 분법으로서 괄호 없이 사용하려면 무조건 해당 함수를 바인드해줘야 한다.


  • 바인드를 하기 번거로운 경우 (화살표 함수 이용 : 자동바인드)

  • 클래스 필드 Syntax 도 사용하지 않는 경우

이 경우 MyButton 컴포넌트가 랜더링 될 때마다 다른 콜백 함수가 생성되는 문제가 있다.
대부분의 경우는 상관없지만 이 콜백 함수가 하위 컴포넌트에 prop 으로 넘겨지게 되면 하위 컴포넌트에서 추가적인 렌더링이 발생한다. (오버헤드)
(비추)

=> 지금 까지는 클래스 컴포넌트에 대한것들 한번 알고만 넘어가자

4. 함수 컴포넌트 에서의 이벤트

  • 앞선 Toggle 클래스 컴포넌트를 함수 컴포넌트로 변환함

클래스 컴포넌트와 달리 this 로 바인드가 필요 없다. 그리고 그냥 쓰면 됨

5. Arguments를 전달하기 (이벤트 핸들러에)

개념 : 함수에 주장할 내용 (전달할 데이터) == 파라미터 (매개변수)

  • 클래스 컴포넌트

코드 두줄 모두 동일한 역할을 한다. event 는 리액트의 이벤트 객체를 의미한다.
첫 줄의 경우는 명시적으로 event 객체를 전달한다는 의미
두번째 줄의 경우는 자동으로 id 를 bind 를 통해 전달하면 암묵적으로 event 객체가 전달된다.

  • 함수 컴포넌트

위와 같이 매개변수를 전달한다. 매개변수의 순서는 원하는대로 해도 됨

5. 실습해보기

  • 클래스 컴포넌트에서 bind 를 통한 구현 예시
import React from "react";

class ConfirmButton extends React.Component{
    constructor(props){
        super(props);

        this.state = {
            isConfirmed : false,
        };

        this.handleConfirm = this.handleConfirm.bind(this); // 바인딩

    }

    handleConfirm(){
        this.setState((prevState) =>( {
            isConfirmed : !prevState.isConfirmed,
        }));
    }

    render(){
        return <button
            onClick={this.handleConfirm}
            disabled={this.state.isConfirmed}
            >
                {this.state.isConfirmed ? "확인됨" : "확인하기"}
        </button>
    }
}

export default ConfirmButton;

  • class fields syntax 사용하기

위 코드에서


(위 바인딩 부분을 제거후 아래와 같이 handleConfirm()을 화살표 함수로 변경하면됨

  • 함수 컴포넌트 이용하기
import React from "react";

function ConfirmButton(props) {
    const [isConfirmed , setIsConfirmed] = useState(false);

    const handleConfirm = () =>{
        setIsConfirmed((prevIsConfirmed) => !prevIsConfirmed)
    }

    // isConfirmed 가 참이면 disabled 시키기
    return(
        <button onClick={handleConfirm} disabled={isConfirmed}> 
            {isConfirmed ? "확인됨" : "확인하기"}
        </button>
    )
}

export default ConfirmButton;

결과는 위와 동일하다. 역시 화살표 함수를 사용함
일반적인 function handleConfirm(){} 로 해도 실행 됨
(클래스 컴포넌트에서는 화살표 유무가 바인드 유무 차이가 있었음)


2. Conditional Rendering

조건부 렌더링 (조건문 이용)

0. 개요

  • 예시

유저의 상태에 따라 위 컴포넌트는 다르게 나타난다. (선택화 해야함)

변수에 상태에 따라 결과가 달라지게 된다.

1. JavaScript의 Truthy와 Falsy

  • Truthy : true 는 아니지만 true 로 여겨지는 값
  • Falsy : false 는 아니지만 false 로 여겨지는 값

2. Element Variable

  • 개념 : 렌더링 해야 될 컴포넌트를 변수처럼 다루고 싶은 경우 사용함

위와 같은 로그인, 로그아웃 버튼 컴포넌트가 존재

사용자의 로그인 여부에 따라 앞에 나온 로그인 버튼과 로그아웃 버튼 컴포넌트를 선택적으로 보여준다.
button 이라는 변수에 컴포넌트를 선택적으로 넣어서 보여주고 있다.
(실제로는 컴포넌트로 부터 생성된 리액트 엘리먼트)

3. Inline condition

  • 개념 : 조건문을 코드 안에 집어 넣는 것

1) InlineIf (&& 연산자를 이용)

  • 조건문 단축 연산

조건문이 true 이면 오른쪽 엘리먼트가 결과 값 false 이면 false 가 나온다.

단축 연산에 의해 0보다 큰 경우에만 오른쪽 부분이 렌더링 된다.
유의 사항 : &&연산자를 사용할 때 조건문에 falsy expression 을 사용하면 뒤에 나오는 expression은 평가되지 않지만 falsy expression 의 결과 값이 그대로 리턴되기 때문에 주의해야 한다.

위 경우 코드를 실행하면 아무 것도 안나오는 것이 아니라 count 의 값인 0이 출력된다.

2) Inline If-Else (? 연산자를 이용 : 삼항 연산자)

  • 개념 : 보여주거나 안 보여주는 두 가지 경우와, 조건문의 값에 따라서 다른 에릴먼트를 보여줄 때 사용

  • 사용 예시

1) 문자열 예시

삼항연산자를 이용하여 isLoggedIn 의 값에 따라 다른 출력을 한다.

2) 엘리먼트 예시

isLoggedIn 이 참 거짓에 따라 다른 컴포넌트가 출력되도록 함 (렌더링 되도록 함)

3) Component 랜더링 막기

  • 방법 : null 을 리턴하면 렌더링 되지 않음

showWarning 이라는 state 값을 warningBanner 컴포넌트의 props 로 전달하여 showWarning 값에 따라 해당 컴포넌트를 표시 또는 표시하지 않는다.

  • 참고로 class 컴포넌트의 렌더 함수에서 null 을 리턴하는 것은 컴포넌트의 생명주기 함수에 전혀 영향을 미치지 않는다.

4) 실습

1) Toolbar.jsx

import React from "react";

const styles = {
    wrapper : {
        padding : 16,
        display : "flex",
        flexDirection : "row",
        borderBottom : "1px solid grey",
    },
    greeting : {
        marginRight: 8,
    },
}

function Toolbar(props){
    const {isLoggedIn, onClickLogin, onClickLogout} = props;

    return(
        <div style={styles.wrapper}>
            {isLoggedIn && <span style={styles.greeting}>환영합니다.</span>}

            {isLoggedIn ? (
                <button onClick={onClickLogout}>로그아웃</button>
            ):(
                <button onClick={onClickLogin}>로그인</button>
            ) }
        </div>
    )
}

export default Toolbar;

2) LandingPage.jsx

import React, {useState} from "react";
import Toolbar from "./Toolbar";

function LandingPage(props){
    const[isLoggedIn, setIsLoggedIn] = useState(false); // 초기 비로그인

    const onClickLogin = () =>{
        setIsLoggedIn(true);
    }
    
    const onClickLogout = () =>{
        setIsLoggedIn(false);
    }

    return(
        <div>
            <Toolbar
            isLoggedIn={isLoggedIn}
            onClickLogin={onClickLogin}
            onClickLogout={onClickLogout}
            ></Toolbar>
            <div style={{padding:16}}>태우와 함께하는 리액트 공부!!</div>
        </div>
    )
}

export default LandingPage;
  • 결과

LandingPage 컴포넌트 내부에서 사용되는 Toolbar 컴포넌트를 구현하는데 이때 조건에 따른 렌더링을 일어나게 하기 위해 InlineIf InlineIfElse 를 사용한다.

profile
잘 부탁드립니다.

0개의 댓글