본문 바로가기

React

React 시작하기 - 07 - 조건부 렌더링, 조건에 따라 다른 요소 렌더링

특정 값이 조건식에 따라서 엘리먼트를 보여주거나 안 보여줄 수 있다.

또는 이 엘리먼트를 보여주거나 저 엘리먼트를 보여줘야 할 때도 있다.

리액트에서는 이러한 조건부 렌더링을 어떻게 처리할까.

<body>
    

    <div id="root1">
    </div>
    <div id="border1"></div>


    <div id="root2">
    </div>
    <div id="border2"></div>


    <div id="root3">
    </div>
    <div id="border3"></div>


    <div id="root4">
    </div>
    <div id="border4"></div>


    <div id="root5">
    </div>
    <div id="border5"></div>


    <!-- react cdn -->
    <script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
    <!-- react dom cdn -->
    <script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
    <!-- babel cdn -->
    <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>

    <!-- define type as a babel  -->
    <script type="text/babel">
        class MakeBorder extends React.Component {
            render() {
                return <p>--------------------------------root{this.props.num}----------------------------</p>;
            }
        }

        // 조건부 렌더링
        // React에서 조건부 렌더링은 JavaScript에서의 조건 처리와 같이 동작한다.
        // if나 조건부 연산자와 같은 JavaScript 연산자를 활용할 수 있다.

        // 캡슐화하기
        // React에서는 원하는 동작을 캡슐화하는 컴포넌트를 만들 수도 있다.
        // 예를 들어 인사말을 출력하는 아래 두 컴포넌트를 보자.
        function UserGreeting(props) {
            return <h1>Welecome back!</h1>;
        }
        function GuestGreeting(props) {
            return <h1>Please sign up.</h1>;
        }
        // 로그인 상태에 따라서 위 두 컴포넌트 중에 하나를 출력하고 싶다면 어떻게 해야 할까.
        // 위 두 컴포넌트를 하위 컴포넌트로 가지는 상위 컴포넌트를 하나 더 만들고 그 안에 조건에 따라서 둘 중 하나를 출력하도록 보자.
        function Greeting(props) {
            const isLoggedIn = props.isLoggedIn;
            if (isLoggedIn) {
                return <UserGreeting />;
            }
            return <GuestGreeting />;
        }
        ReactDOM.render( <Greeting isLoggedIn={false} />, document.getElementById('root1') );
        ReactDOM.render( <MakeBorder num="1" />, document.getElementById('border1') );


        // 리액트 요소를 변수에 넣기
        // 리액트 요소를 변수에 저장할 수도 있다.
        // 다른 부분은 그대로 둔 채로 컴포넌트의 일부분만 조건에 따라 렌더링할 수 있다.
        // 예를 들어 로그인 또는 로그아웃 버튼을 나타내는 아래 두 컴포넌트를 보자.
        function LoginButton(props) {
            return (
                <button onClick={props.onClick}>
                    Login
                </button>
            );
        }
        function LogoutButton(props) { 
            return (
                <button onClick={props.onClick}>
                    Logout
                </button>
            );
        }
        // 위 두 컴포넌트를 하위 컴포넌트로 갖는 상위 컴포넌트를 하나 만들어 보자.
        class LoginControl extends React.Component {
            constructor(props) {
                super(props);
                this.handleLoginClick = this.handleLoginClick.bind(this);
                this.handleLogoutClick = this.handleLogoutClick.bind(this);
                this.state = {isLoggedIn: false};
            }

            handleLoginClick() {
                this.setState({isLoggedIn: true});
            }
            handleLogoutClick() {
                this.setState({isLoggedIn: false});
            }
            
            render() {
                const isLoggedIn = this.state.isLoggedIn;
                let button;
                // button 이라는 이름으로 변수를 만들어 놓고, isLoggedIn 라는 값에 따라 다른 React 요소를 넣어 둔다.
                // 출력할 때는 중괄호 {} 안에 변수명만 넣어주면 된다.
                if(isLoggedIn) {
                    button = <LogoutButton onClick={this.handleLogoutClick} />;
                } else {
                    button = <LoginButton onClick={this.handleLoginClick} />;
                }

                return (
                    <div>
                        <Greeting isLoggedIn={isLoggedIn} />
                        {button}
                    </div>
                );
            }
        }
        ReactDOM.render( <LoginControl />, document.getElementById('root2') );
        ReactDOM.render( <MakeBorder num="2" />, document.getElementById('border2') );


        // 논리 연산자 사용하기
        // JSX 문법 안에서는 중괄호 {}를 활용해서 JavaScript 표현식을 사용할 수 있다.
        // 논리 연산자 && 를 사용하면 조건에 따라 다르게 보여주는 기능을 쉽게 만들 수 있다.
        // if( 조건식 ) {  출력할 요소 } 
        // 위 내용을 아래처럼 줄여서 표현할 수 있다.
        // { 조건식 && React 요소 } 
        // 예를 들어 아래 컴포넌트를 보자.
        // 이 컴포넌트는 리스트 안에 요소가 있을 때만 메세지를 출력한다.
        function MailBox(props) {
            const unreadMessages = props.unreadMessages;
            return (
                <div>
                    <h1>Hello!</h1>
                    { unreadMessages.length > 0 && 
                        <h2>
                            You have {unreadMessages.length} unread messages.
                        </h2>
                    }
                </div>

            )
        }
        const messages = ['React', 'Re: React', 'Re:Re: React'];
        ReactDOM.render( <MailBox unreadMessages= {messages} />, document.getElementById('root3') );
        ReactDOM.render( <MakeBorder num="3" />, document.getElementById('border3') );
        
        // JavaScript에서 true && expression은 항상 expression으로 평가되고 false && expression은 항상 false로 평가된다.
        // 즉, 논리 연산자 && 뒤에 있는 표현식은, 논리 연산자 && 앞에 있는 조건식에 따라서 출력되거나 출력되지 않는다.
        // 단, falsy 표현식을 반환하면 여전히 && 뒤에 있는 표현식은 건너뛰지만 falsy 표현식이 반환된다는 점에 유의하자.
        // 예를 들어 아래에서는 <div>0</div> 가 출력된다.
        // render() {
        //     const count = 0;
        //     return (
        //         <div>
        //             {count && <h1>Messages: {count}</h1>}
        //         </div>
        //     );
        // }


        // 삼항연산자를 사용하여 If-Else구문 인라인으로 표현하기
        // 조건에 따라 리액트 요소를 나타내거나 나타내지 않는 방법을 알아보고 있다.
        // 앞에서는 중관호 {} 안에 논리 연사자 && 를 활용하여 요소가 출력될지 여부를 결정했다.
        // 비슷한 방법으로 삼항 연사자  condition ? true: false 를 활용하는 방법도 있다.
        // 내용이 앞과 비슷하고 어렵지 않으므로 예시만 보고 넘어가자.
        // 아래는 isLoggedIn 에 따라서 메세지 내용이 바뀐다.
        // render() {
        // const isLoggedIn = this.state.isLoggedIn;
        //     return (
        //         <div>
        //             The user is <b>{isLoggedIn ? 'currently' : 'not'}</b> logged in.
        //         </div>
        //     );
        // }
        // 가독성은 떨어지지만 아래처럼 더 큰 표현식을 넣거나 컴포넌트를 넣을 수도 있다.
        // render() {
        //     const isLoggedIn = this.state.isLoggedIn;
        //     return (
        //         <div>
        //             {isLoggedIn
        //                 ? <LogoutButton onClick={this.handleLogoutClick} />
        //                 : <LoginButton onClick={this.handleLoginClick} />
        //             }
        //         </div>
        //     );
        // }



        // 컴포넌트가 렌더링되지 않도록 막기
        // 다른 컴포넌트에 따라서 특정 컴포넌트 자체를 숨길지 말지 결정할 수도 있다.
        // 이때는 리액트 요소를 반환하지 말고, null을 반환하면 된다.
        // 아래 예시를 보자.
        // 아래에서는 < WarningBanner />가 warn이라는 props 값에 따라서 렌더링된다.
        // 만약 warn이 false라면 렌더링 자체를 하지 않는다.
        function WarningBanner(props) {
            if(!props.warn) {
                return null;
            }

            return (
                <div className="warning">
                    Warning!
                </div>
            );
        }

        class Page extends React.Component {
            constructor(props) {
                super(props);
                this.state = {showWarning: true};
                this.handleToggleClick = this.handleToggleClick.bind(this);
            }

            handleToggleClick(){
                this.setState(state=> ({
                    showWarning: !state.showWarning
                }));
            }

            render() {
                return (
                    <div>
                        <WarningBanner warn={this.state.showWarning} />
                        <button onClick={this.handleToggleClick}>
                            { this.state.showWarning ? 'Hide' : 'Show' }
                        </button>
                    </div>
                );
            }
        }

        ReactDOM.render( <Page />, document.getElementById('root4') );
        ReactDOM.render( <MakeBorder num="4" />, document.getElementById('border4') );
        
    </script>
</body>

- 220529

 

참고자료 -

https://ko.reactjs.org/docs/conditional-rendering.html

반응형