Conditional Rendering


React에서는 필요한 기능을 캡슐화한 고유한 컴포넌트를 만들 수 있다. 그리고 애플리케이션의 상태에 따라 이들 중 
일부만 렌더링할 수 있다.


React에서의 조건부 렌더링은 자바스크립트에서 조건문이 하는 방식과 동일하게 작동한다. 자바스크립트의 if나 
조건 연산자같은 연사자들을 이용하여 현재 상태를 표시할 elements를 생성할 수도 있고, React가 거기에 맞춰
UI를 업데이트하도록 할 수도 있다.


아래의 두 component를 살펴보자

function UserGreeting(props) {
  return <h1>Welcome back!</h1>;
}

function GuestGreeting(props) {
  return <h1>Please sign up.</h1>;
}


사용자가 로그인 했는지의 여부에 따라 이들 중 하나의 component를 표시하는 Greeting이라는 component를
만들 수 있을 것이다.

function Greeting(props) {
  const isLoggedIn = props.isLoggedIn;
  if (isLoggedIn) {
    return <UserGreeting />;
  }
  return <GuestGreeting />;
}

ReactDOM.render(
  // Try changing to isLoggedIn={true}:
  <Greeting isLoggedIn={false} />,
  document.getElementById('root')
);

CodePen에서 살펴보기.


이 예제는 isLoggedIn이라는 prop의 값에 따라 다른 greeting을 렌더링 한다.


Element Variables


elements를 저장하기 위해 변수들을 사용할 수 있다. 이렇게 할 경우 출력의 나머지 부분이 변경되지 않고 있는 상태에서
일부 component를 조건부로 렌더링 하는데 도움이 된다.


로그인 버튼과 로그아웃 버튼을 표시하는 새로운 두 개의 component를 살펴보자

function LoginButton(props) {
  return (
    <button onClick={props.onClick}>
      Login
    </button>
  );
}

function LogoutButton(props) {
  return (
    <button onClick={props.onClick}>
      Logout
    </button>
  );
}


이 component들 아래에 LoginControl이라는 상태를 갖는 component를 만들 것이다.


이 component는 자신의 현재 상태에 따라 <LoginButton /> 또는 <LogoutButton />를 렌더링 할 것이다.
또한 이전 예제에서 보았던 <Greeting />도 렌더링 할 것이다.

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 = null;
    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('root')
);

CodePen에서 살펴보기.


변수를 선언하고 if문을 사용하는 것은 component를 조건부로 렌더링하는 좋은 방법이며, 때때로 더 짧은
문법을 사용하는 것이 더 좋을 것이다. JSX에는 몇가지 inline 조건 처리 방법이 있는데 아래에서 설명할 것이다.


Inline If with Logical && Operator


중괄호({})를 사용함으로써 JSX의 어떤 표현식들을 내장시킬 수 있다. 여기에는 자바스크립트의 논리 연산자인
&&이 포함된다. 이 연산자를 사용하는 것이 조건부로 element를 포함시키는데 더 편한 경우도 있다.

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('root')
);

CodePen에서 살펴보기.


이 예제는 자바스크립트 내에서 실행되기 때문에 true && expression은 항상 expression의 값을 갖게 되며
false && experssion은 항상 false의 값을 갖게 된다.


그러므로 만일 조건이 true라면 && 오른쪽의 element가 출력으로 표시된다. 반면에 조건이 false라면
React는 이 문장을 무시하고 건너 뛸 것이다.


Inline If-Else with Conditional Operator


elements를 inline으로 조건부 렌더링하는 방법에는 자바스크립트의 조건 연산자인 condition ? true : false 를 

사용하는 방법도 있다.


아래의 예제에서 작은 텍스트 블록을 렌더링 하기 위해 이 방법을 사용할 것이다.

render() {
  const isLoggedIn = this.state.isLoggedIn;
  return (
    <div>
      The user is <b>{isLoggedIn ? 'currently' : 'not'}</b> logged in.
    </div>
  );
}
It can also be used for larger expressions although it is less obvious what's going on:

render() {
  const isLoggedIn = this.state.isLoggedIn;
  return (
    <div>
      {isLoggedIn ? (
        <LogoutButton onClick={this.handleLogoutClick} />
      ) : (
        <LoginButton onClick={this.handleLoginClick} />
      )}
    </div>
  );
}


자바스크립트에서와 마찬가지로 어떤 것이 더 가독성이 좋은가 하는 선택은 당신에게 달려있다. 또한 조건이 더 복잡해
진다는 것은 component를 분리하기에 좋은 시점이란 것을 명심하자.


Preventing Component from Rendering


아주 드문 경우로 어떤 component가 다른 component로부터 렌더링 되었음에도 불구하고 숨겨야 할 경우가 있다.
이런 경우 렌더링될 출력값 대신 null을 리턴하면 된다.


아래의 예제에서 <WarningBanner />는 warn이라는 prop의 값에 따라 렌더링이 결정된다. 만일 prop의 값이
false라면 component는 렌더링되지 않는다.

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(prevState => ({
      showWarning: !prevState.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('root')
);

CodePen에서 살펴보기.


component로부터 null을 리턴받게 되는 경우 render 메소드는 component의 lifecycle 메소드들을
작동시키지 않는다. 하지만 componentWillUpdate와 componentDidUpdate는 여전히 호출된다.







'Study > React' 카테고리의 다른 글

React 살펴보기 #8  (0) 2017.05.15
React 살펴보기 #7  (0) 2017.04.20
React 살펴보기 #6  (0) 2017.03.27
React 살펴보기 #5  (0) 2017.03.04
React 살펴보기 #4  (0) 2017.02.17
React 살펴보기 #3  (0) 2017.02.11
블로그 이미지

마즈다

이미 마흔을 넘어섰지만 아직도 꿈을 좇고 있습니다. 그래서 그 꿈에 다가가기 위한 단편들을 하나 둘 씩 모아가고 있지요. 이 곳에 그 단편들이 모일 겁니다...^^