- 이 글은 React 공식 홈페이지 Docs v16.8.3 (https://reactjs.org/docs) 에 기반하여 작성한 글입니다.
- Conditional Rendering
React 에서 Rendering 하고 싶은 element 들을 캡슐화해서 Component 단위로 만들 수 있다. 그리고 이런 Component 들을 state 상태에 따라서 조건부 렌더링을 할 수 있다.
React 에서 조건부 렌더링은 Javascript 에서 분기문과 같은 방법으로 동작한다. if 문이나 조건부 문법을 사용해서 elements 를 만들면 React 는 이 element 에 맞춰서 UI를 갱신한다.
아래 2개의 component 가 있다고 가정하자.
2개의 Component 를 화면에 이상없이 출력하였다. login 상태에서는 환영문구를 보여주고, login을 하지 않았다면 회원가입(sign up) 하라는 사이트를 많이 보았을 것이다. 유저 login 여부에 따라 둘 중 1문구만을 보여주는 Component 를 추가해보자.
Greeting component 에 전달된 props 의 isLoggedIn attribute 값에 따라서 문구가 바뀌는 것을 확인할 수 있다.
- element variables
element 를 변수에 저장할 수도 있다. 물론 app 이 동작하는데에는 차이가 없지만 Component 를 부분적으로 rendering 할 때 도움이 된다.
Login 여부에 따른 환영인사에 이어서 button component 도 만들어 보자.
여태까지 만든 Component 들을 기반으로 상태값에 의존하는(stateful 한) LoginControl component 를 만들어보자.
LoginControl component 는 상태값에 따라서 <Greeting /> component 와 함께 <LoginButton /> 이나 <LogoutButton /> 을 rendering 할 것이다.
LoginControl 을 만들어 보자! 원래 귀찮음을 이겨내지 못하고 복붙해서 돌려보고 끝내는 사악한 유저들을 위해 캡처를 올리나 코드가 너무 긴 관계로 하이라이트로 대체
function UserGreeting(props){
return (
<h1>Welcome back!</h1>
);
}
function GuestGreeting(props){
return (
<h1>Please sign up.</h1>
);
}
function Greeting(props){
const isLoggedIn = props.isLoggedIn;
if(isLoggedIn){
return (<UserGreeting />);
}
return (
<GuestGreeting />
);
}
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.logIn = this.logIn.bind(this);
this.logOut = this.logOut.bind(this);
this.state = {
isLoggedIn : false
};
}
logIn() {
console.log("call logIn");
this.setState({isLoggedIn : !this.state.isLoggedIn});
}
logOut() {
console.log("call logOut");
this.setState({isLoggedIn : !this.state.isLoggedIn});
}
render() {
const isLoggedIn = this.state.isLoggedIn;
let button;
if(isLoggedIn){
button = <LogOutButton onClick={this.logOut}/>;
}
else{
button = <LogInButton onClick={this.logIn}/>;
}
return (
<div>
<Greeting isLoggedIn={this.state.isLoggedIn} />
{button}
</div>
);
}
}
ReactDOM.render(
<LoginControl />,
document.getElementById('root')
)
button 에 component 를 할당하는 if 문 부분을 보자. 가독성도 나쁘지 않고 꽤 괜찮아 보인다. React 는 위처럼 변수에 component 할당을 할 수도 있고, 위와 똑같은 기능을 JSX 안에서 inline 스타일로도 구현할 수 있다.
- Inline If with Logical && Operator
JSX 의 {} 에서 expression 을 사용했던 기억을 떠올려 보자. javascript expression 을 사용할 수 있었다. 그렇다면 눈치 빠른 사람들은 논리연산자에서 && 도 사용할 수 있을 것이라고 생각할 것이다.
{} 안에서 inline 방식으로 아까 코드를 변경해보자.
component 를 할당하기 위한 button 변수가 없어지고 3항 연산자로 대체 했다.
다른 얘제도 한번 적용해보자. 메일이나 메신저 같은 것을 보면 읽지 않은 건들에 대해 counting 을 해서 표시해주는 기능을 많이 보았을 것이다. 메일이라고 가정하고 inline 문법을 이용해서 구현해보자.
Message 가 있을 때에는 건수가 표시되고 없을 때에는 환영문구만 표시된다. 회사원들에게 끔찍한 Re: Fw:는 덤
message의 길이가 0 이상이면 true && element 여서 element 를 출력하지만 message 가 비어있어서 길이가 0이면 false && element 일 때 출력하지 않는것을 확인할 수 있다.
JSX 안에서 {} 에 대한 평가식이 false 일 때 rendering 을 하지 않으며, element 는 boolean 평가식에서 true 로 취급됨을 알 수 있는 대목이다.
- Inline If-Else with Conditional Operator
Javascript 의 조건부 연산자에 3항 연산자가 있다. (condition ? true : false)
그럴의도는 아니였는데 login logout 버튼을 {} 안에서 inline 방식을 소개할 때 3항 연산자를 써버렸다. 3항 연산자를 쓸 때 길이가 긴 element 를 표현하고자 한다면 확실하게 구분하게 해주기 위해 () 를 추가해줄 수도 있겠다.
{} 에는 Javascript 표현식을 모두 쓸 수 있으므로,(굳이 기억할 필요 없다. JSX 가 Javascript XML 약자임을 떠올려 보면 알 것이다.) 적절하게 잘 활용하면 될 것이다.
1가지만 기억하면 된다. 표현하고자 한 element 가 길어질 경우 () 로 구분할 수 있어서 문법적으로는 이상이 없지만 동료개발자들의 눈을 보호해주기 위해 component 단위로 따로 뺄 수 있지 않을까 하는 의심을 언제나 가지자. 리팩토링 개념을 알고 있는 사람이라면 언제나 긴 코드에는 bad smell 이 난다는 사실을 기억하면 될 것 같다.
- Preventing Component from Rendering
Rendering을 하기 위해서 component 를 사용하는건데 rendering 을 방지하는 component 라니 이게 무슨소리 인가? 한국말은 끝까지 들어보라더니 영어도 별반 다를 건 없다. 드문 경우이긴 하겠지만 다음과 같은 경우가 필요할 수도 있다.
자기 자신은 Rendering 하지 않지만, 다른 Component 에 의해서 Rendering 되는 component 라면 위의 소제목이 이해가 갈 것이다.
return 문에 무조건 element 를 할당하면 해당 Component 를 사용할 때 그려질텐데 어떻게 가능하단 말인가. 눈치가 빠른 사람이라면 이미 눈치 챘겠지만 return 문에 null 을 할당하면 된다.
사용자에게 위험사항이 있을 때만 출력해주는 <Warning Banner /> component 를 만들어 보자. prop값이 false 이면 component 가 rendering 이 되지 않게 하자.
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({showWarning: !this.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('root')
)
똑똑한 코더라면 render 에서 null을 return 하면 lifecycle method 에 영향을 주는 것이 아닌가라고 생각할 수도 있다. render method 에서 null 을 return 하더라도 component 의 lifecycle method 에 영향을 주지 않는다.
componentDidUpdate 는 여전히 호출 될 것이다. 라면서 친절하게 설명해주지만 검증을 해보자.
구라는 아닌가보다.
'Language > React' 카테고리의 다른 글
[React 공식 Doc 가이드 #10] Forms (0) | 2021.02.11 |
---|---|
[React 공식 Doc 가이드 #9] Lists and Keys (0) | 2021.02.11 |
[React 공식 Doc 가이드 #7] Handling events (0) | 2021.02.11 |
[React 공식 Doc 가이드 #6] State and Lifecycle (0) | 2021.02.11 |
[React 공식 Doc 가이드 #5] Components and Props (0) | 2021.02.11 |
댓글