Conditional Rendering

- 조건에 따른 렌더링(조건부 렌더링)
- 어떠한 조건에 따라서 렌더링이 달라지는 것
- 예) Ture이면 버튼을 보여주고 False이면 버튼을 가린다.

만약 로그인됐으면 유저를 환영한다는 컴포넌트를 반환하고, 그렇지 않으면 게스트를 환영한다는 컴포넌트를 반환

 

 

Truthy, Falsy

- true는 아닌데 true로 여겨지는 값
- false는 아니지만 false로 여겨지는 값

truthy와 falsy의 예



 

Element Variables

- 렌더링 해야하는 컴포넌트를 변수처럼 사용해야 할 때

button이라는 변수에 컴포넌트를 집어넣어서 리턴하는 방식

 


Inline Condition

- 코드를 별도로 분리하지 않고, 조건문을 코드 안에 집어넣음

 

 

Inline If

- If문의 경우 && 연산자를 사용
- true && expression 첫번째 조건문이 true라서 두번째 expression 문도 평가함
- false && expression 첫번째 조건문이 false면 두번째 expression 문은 굳이 평가하지 않음
- 그래서 위의 결과값은 expression이고 아래의 결과값은 false

읽지않은 메세지 갯수가 0보다 클 경우 해당 태그를 리턴하지 않고, 0보다 작을 경우 해당 태그 리턴



 

Inline If-Else

- ? 연산자를 사용
- 조건에 따라 각기 다른 Element를 렌더링 하고 싶을 때 사용
- condition ? true : false (삼향연산자)

삼향연산자, 로그인되었다면 '로그인'을 반환하고 아니라면 '로그인하지 않은'을 반환
이 역시, 로그인 여부에 따라 반환하는 컴포넌트를 다르게 함



 

 

Component 렌더링 막기

- null을 리턴하면 렌더링 되지 않음

경고 메세지가 없다면 null을 반환하고 경고 메세지를 나타나게 하지 않음
showWarning의 값에 따라 경고 메세지를 감추거나 보이게 할 수 있음

 

 

 

 

 

실습 : 로그인 여부를 나타내는 툴바 만들기

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

 

툴바 컴포넌트를 만든다. 로그인 여부에 따라 환영 인사를 보여주고, 로그인, 로그아웃 버튼을 보여주는 방식이다.

 

 

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

// useState 훅을 이용해 사용자의 로그인여부를 자체적으로 관리
function LandingPage(props) {
    const [isLoggedIn, setIsLoggedIn] = useState(false);

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

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

    // Toolbar 컴포넌트에 전달
    return (
        <div>
            <Toolbar
                isLoggedIn={isLoggedIn}
                onClickLogin={onClickLogin}
                onClickLogout={onClickLogout}
            />
            <div style={{ padding: 16 }}>리액트 공부 같이해요!</div>
        </div>
    );
}

export default LandingPage;

useState 훅을 이용해 사용자의 로그인 여부를 저장한다. 역시 처음에는 false가 초기값이다.  누르면 로그인 여부를 바꿔주는 onClickLogin과 onClickLogout을 Toolbar 컴포넌트에 전달하고, 로그인 여부가 저장되어 있는 isLoggedIn 역시 전달한다. 전달 받은 값들을 위의 Toolbar 컴포넌트에서 활용하면 된다.

 

 

 

 

로그인 버튼을 누르면 환영 메세지가 뜨고, 로그아웃 버튼을 반환한다. 로그아웃 버튼을 누르면 원래대로 돌아가게 된다.

'React' 카테고리의 다른 글

[React] Form과 Controlled Component  (0) 2024.08.18
[React] List 와 Key  (0) 2024.08.13
[React] Event  (0) 2024.08.08
[React] Hooks 실습  (0) 2024.08.07
[React] Hooks  (0) 2024.08.06

Event

- 특정 사건을 의미
- 예) 사용자가 버튼을 클릭한 사건 : 버튼 클릭 이벤트

 

 

 

DOM의 Event와 리액트의 Event 비교

DOM의 Event
리액트의 Event

 

- 리액트의 onClick은 카멜 표기법으로
- 함수 전달 방식에 약간 차이있음

 

Event Handler

- 어떤 사건이 발생하면, 사건을 처리하는 역할
- Event Listener라고 부르기도 함

 

 

- Arrow function 사용은 권장되는 방식이 아니다. 그러니 Bind 혹은 Class fields syntax 를 사용하는 것이 좋다.

 

 

Arguments 전달하기

- Arguments는 함수에 전달할 데이터, Event Handler에 전달한 데이터, 매개변수 역할

위는 Arrow function 을 사용하여 Event Handler에 Arguments를 전달한 것이고, 아래는 bind를 사용하였다. Arrow function으로 사용한 방식은 명시적으로 event를 두번재 매개변수로 넣어주었고, 아래 bind 방법은 Event가 자동으로 id 이후에, 두번째 매개변수로 전달된다. 위의 두 방식은 Class 컴포넌트에서 사용하는 방식이므로 지금은 거의 사용하지 않는다.

 

 

 

 

함수 컴포넌트에서 사용법. 참고로 매개변수의 순서는 원하는대로 변경해도 상관없다.

 

 

 

 

실습 : 클릭 이벤트 처리하기

1) Bind를 사용한 방식 (Class Component)

import React from "react";

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

        // 확인여부 저장위함 (초깃값 false)
        this.state = {
            isConfirmed: false,
        };

        this.handleConfirm = this.handleConfirm.bind(this);
    }

    // Event Handler : 버튼을 누르면 실행됨
    handleConfirm() {
        this.setState((prevState) => ({
            isConfirmed: !prevState.isConfirmed,
        }));
    }

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

export default ConfirmButton;
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';

import ConfirmButton from './chapter_08/ConfirmButton';


ReactDOM.render(
  <React.StrictMode>
  <ConfirmButton />
  </React.StrictMode>,
  document.getElementById('root')
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

 

실행하면, 확인하기 버튼 하나가 생성되는데, 누르면 확인됨으로 변경되고, 버튼이 비활성화 되는 것을 확인할 수 있다.

 

 

 

 

2) Class fields syntax 를 사용한 방식 (Class Component)

import React from "react";

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

        // 확인여부 저장위함 (초깃값 false)
        this.state = {
            isConfirmed: false,
        };
    }

    // Event Handler : 버튼을 누르면 실행됨
    handleConfirm = () => {
        this.setState((prevState) => ({
            isConfirmed: !prevState.isConfirmed,
        }));
    }

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

export default ConfirmButton;

 

bind를 사용한 부분을 지우고, 이벤트 핸들러를 Arrow function으로 변경한다. 실행결과 동일하게 작동된다.

 

 

 

 

3) 함수 컴포넌트로 바꿔보기 (권장)

- Class Component는 거의 사용하지 않기 때문에 이 방법을 가장 권장함

 

import React, { useState} from "react";

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

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

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

export default ConfirmButton;

 

state는 useState() 훅을 사용해 처리, EventHandler는 Arrow function 이용해 만듦. 작동시킨 결과, 역시 동일한 결과가 나온다.

'React' 카테고리의 다른 글

[React] List 와 Key  (0) 2024.08.13
[React] Conditional Rendering  (0) 2024.08.12
[React] Hooks 실습  (0) 2024.08.07
[React] Hooks  (0) 2024.08.06
[React] State and Lifecycle  (0) 2024.08.03
import React, { useState } from "react";
// 카운트 기능
function useCounter(initialValue) {
    const [count, setCount] = useState(initialValue);

    const increaseCount = () => setCount((count) => count + 1);
    const decreaseCount = () => setCount((count) => Math.max(count -1, 0));

    return [count, increaseCount, decreaseCount];
}

export default useCounter;

우선 버튼을 누르면 카운트가 바뀌는 커스텀 훅을 작성한다. useState() 는 현재 카운트의 상태를 생성 및 업데이트 해주는 역할을 한다.

 

 

 

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

const MAX_CAPACITY = 10;

function Accommodate(props) {
    const [isFull, setIsFull] = useState(false);
    const [count, increaseCount, decreaseCount] = useCounter(0);

    // 의존성 배열 없음 (마운트 된 직후 호출, 컴포넌트 업데이트 때마다 호출)
    useEffect(() => {
        console.log("=====================");
        console.log("useEffect() is called");
        console.log(`isFull: ${isFull}`);
    });

    // 의존성 배열 있음 (마운트 된 직후 호출, 카운트 값이 바뀔때 마다 호출)
    useEffect(() => {
        setIsFull(count >= MAX_CAPACITY);
        console.log(`Current count value: ${count}`);
    }, [count]);

    return (
        <div style={{ padding: 16 }}>
            <p>{`총 ${count}명 수용했습니다.`}</p>

            <button onClick={increaseCount} disabled={isFull}>
                입장
            </button>
            <button onClick={decreaseCount}>퇴장</button>

            {isFull && <p style={{ color : "red" }}> 정원이 가득찼습니다.</p>}
        </div>
    );
}

export default Accommodate;

useEffect()를 이용해보았다. 의존성 배열 있는것과 없는 것을 비교하기 위해 다음과 같이 작성하였다.

 

 

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';

import Accommodate from './chapter_07/Accommodate';


ReactDOM.render(
  <React.StrictMode>
  <Accommodate />
  </React.StrictMode>,
  document.getElementById('root')
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

인덱스에서 렌더링하는거 잊지 말고...

 

 

 

맨 처음에 콘솔창을 열어보면 컴포넌트가 생성되고, 카운트값의 초기값이 생성되었기에 두개의 useEffect() 훅이 마운트 된 직후에 호출된 걸 확인할 수 있다. 그리고 입장 버튼을 누르면, 컴포넌트가 업데이트되고, 카운트 값도 변경되니, 이 역시 두개의 useEffect() 훅이 호출된다.

 

 

 

 

그러나 정원이 꽉 차게 된다면, 일단 두개의 훅이 호출되는데, 그 후 또 하나의 useEffect() 훅이 호출된다. 이는 정원이 꽉 차게 되어 isFull의 상태가 변하기 때문에 컴포넌트가 업데이트 되어, 정원이 꽉 차게 되었다는 걸 알리는 useEffect() 훅이 호출된다. 하지만 count라는 의존성 배열이 있는 useEffect() 훅은 카운트 값의 변화가 없기 때문에 호출되지 않는다.

 

 

 

 

 

퇴장 버튼을 0이 될 때까지 누르고, 0이 되어서 계속 퇴장버튼을 눌러도 두개의 useEffect 훅 모두 호출되지 않는다. 의존성 배열인 count의 값이 변하는 것도 아니고, isFull의 상태 역시 변하는 것이 아니기 때문에 컴포넌트가 업데이트 되지 않기 때문이다.

'React' 카테고리의 다른 글

[React] Conditional Rendering  (0) 2024.08.12
[React] Event  (0) 2024.08.08
[React] Hooks  (0) 2024.08.06
[React] State and Lifecycle  (0) 2024.08.03
[React] Components 와 Props  (0) 2024.08.01

+ Recent posts