본문 바로가기
개발

[ReactJS] 조건부 랜더링(Conditional Rendering)

by 마스터누누 2017. 6. 13.
728x90
반응형

조건부 랜더링(Conditional Rendering)



1
2
3
4
5
6
7
function UserGreeting(props) {
  return <h1>Welcome back!</h1>;
}
 
function GuestGreeting(props) {
  return <h1>Please sign up.</h1>;
}
cs


리액트에서는 필요한 동작을 캡슐화하는 컴포넌트를 만들 수 있다.

그런 다음 애플리케이션의 state에 따라 일부만 랜더링 할 수 있다.


리액트의 조건부 랜더링은 자바스크립트에서와 동일하게 동작한다.

if와 같은 자바스크립트의 조건부 연산자를 사용하여 현재 state를 나타내게하는 엘리먼트를 만들고

리액트가 UI를 업데이트 하여 일치하도록 한다.


사용자의 로그인 여부를 출력하는 위의 두 컴포넌트를 만들었다고 했을 때,

이를 관리하는 상위 컴포넌트를 만들어야한다.





1
2
3
4
5
6
7
8
9
10
11
12
13
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')
);
cs


Greeting이 상위 컴포넌트로써 동작하게되는데,

사용자가 로그인 했는지의 여부를 조건문을 통해 판단하므로 결과값에 따라 출력되는 값도 달라진다.

결과적으로, 이 예제는 proprs. isLoggedIn 값에 따라 다른 결과물을 출력한다.





엘리먼트 변수


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function LoginButton(props) {
  return (
    <button onClick={props.onClick}>
      Login
    </button>
  );
}
 
function LogoutButton(props) {
  return (
    <button onClick={props.onClick}>
      Logout
    </button>
  );
}
cs


리액트에서는 변수를 사용해서 엘리먼트를 저장할수 있다.

이렇게 하면 출력의 나머지 부분이 변경되지 않는 동안 조건부로 컴포넌트의 일부를 랜더링하는데 도움이 될 수 있다.

위의 코드는 로그인과 로그아웃 버튼을 나타낸다





1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
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')
);
cs


위의 코드는 이렇게 만들어진 두개의 로그인/로그아웃 버튼을 조건에 따라 컨트롤 하는 예제이다

LoginControl의 현재 state 값에 따라서 로그인/로그아웃 버튼을 출력하게 된다.

또한 제일 위의 예제인 Greeting 도 관리하게 된다.


변수를 선언하고 if로 조건부 랜더링을 하는 것은 좋은 방법이지만 더 짧은 구문을 사용하는 것이 좋다.

아래의 그 방법들에 대한 예제들이다.  




&& 논리 연산자 사용


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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')
);
cs


JSX에서는 중괄호로 묶어서 expression을 삽입할 수 있다. 여기에는 Javascript && 논리 연산자가 포함된다.

컴포넌트를 조건부로 포함하는 것이 편리 할 수 있다.


자바스크립트에서 true&&expression은 항상 expression으로 결과값이 나오며,

false&&expression은 항상 false로 결과값이 나오기 때문에 위의 코드는 무리 없이 잘 동작한다.


따라서 조건이 참 이면 && 다음에 오는 엘리먼트가 출력에 나타나고 거짓이면 리액트는 해당 표현식을 건너 뛴다.




if-else 3항 조건 연산자 사용


1
2
3
4
5
6
7
8
render() {
  const isLoggedIn = this.state.isLoggedIn;
  return (
    <div>
      The user is <b>{isLoggedIn ? 'currently' : 'not'}</b> logged in.
    </div>
  );
}
cs


엘리먼트를 조건부로 랜더링하는 방법은 자바스크립트 3항 조건 연산자를 사용하는 것이다.

위의 예제는 isLoggedIn의 값에 따라 문자열값을 다르게 삽입하는 것을 보여준다.




1
2
3
4
5
6
7
8
9
10
11
12
render() {
  const isLoggedIn = this.state.isLoggedIn;
  return (
    <div>
      {isLoggedIn ? (
        <LogoutButton onClick={this.handleLogoutClick} />
      ) : (
        <LoginButton onClick={this.handleLoginClick} />
      )}
    </div>
  );
}
cs


단순히 문자열이 아닌 더 큰 표현식에도 사용될 수 있지만, 상황이 덜 명확하다.

자바스크립트에서와 마찬가지로 프로젝트를 운영하는 팀이 보다 가독성 있는 코드를 추구한다면 

적절한 스타일을 선택하는 것은 팀의 컨벤션에 달려있다


또한 조건이 더욱 복잡해 질 때마다 컴포넌트를 적절히 추출하여 분리하는것이 좋다.





랜더링에서 컴포넌트 방지


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
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')
);
cs


드문 경우이지만, 컴포넌트가 다른 컴포넌트에 의해 랜더링 되었더라도 컴포넌트를 숨길 수  있다.

이렇게 하려면 랜더링 출력 대신 null을 반환한다.

위의 예제에서는 warn이라는 props 값에 따라 <WanningBanner />를 랜더링한다.

이 prop 값이 false인 경우 컴포넌트는 랜더링을 실행하지 않는다.


컴포넌트의 랜더링 메소드에서 null을 반환해도 컴포넌트의 라이프 사이클 메소드를 호출하는데 영향을 주지 않는다.

예를 들어, componentDidMount와 componentWillUnmount는 여전히 호출된다.





반응형

'개발' 카테고리의 다른 글

[ReactJS] 입력폼(Forms)  (0) 2017.06.13
[ReactJS] 리스트와 키(Lists and Keys)  (0) 2017.06.13
[ReactJS] 이벤트 핸들링(Event Handling)  (0) 2017.06.13
[ReactJS] State와 라이프 사이클  (0) 2017.06.13
[ReactJS] 컴포넌트와 Props  (0) 2017.06.12

댓글