TIL
오늘은 앞서 클론 코딩한 것들을 스스로 구현해보는 시간을 가졌고, 조건부 랜더링과 스타일링, 디버깅에 관한 것들을 배웠습니다.
Conditional Rendering(조건부 랜더링)
if (isLoggedIn) {
button = <LogoutButton onClick={this.handleLogoutClick} />;
} else {
button = <LoginButton onClick={this.handleLoginClick} />;
}
물론 이런식으로 사용할 수 있지만, 더 짧은 구문으로 jsx안에서 인라인(inline)으로 처리할 방법을 소개합니다.
논리 && 연산자로 If를 인라인으로 표현하기
return (
<div>
{isEmpty && <h2>비었습니다.</h2>}
</div>
)
// 더 복잡한 예
return (
{filteredExpenses.length === 0 ? (
<p>No expenses found.</p>
) : (
filteredExpenses.map((expense) => (
<ExpenseItem
key={expense.id}
title={expense.title}
amount={expense.amount}
date={expense.date}
/>
))
)}
)
조건부 연산자(삼항 연산자)로 If-Else구문 인라인으로 표현하기
return (
<div>
{isEmpty ? <h2>비었습니다.</h2> : <h2>남아있습니다.</h2>}
</div>
)
// 더 복잡한 예
return (
{filteredExpenses.length === 0 && <p>No expenses found.</p>}
{filteredExpenses.length > 0 &&
filteredExpenses.map((expense) => (
<ExpenseItem
key={expense.id}
title={expense.title}
amount={expense.amount}
date={expense.date}
/>
))}
)
하지만 js부분은 위로 빼는게 깔끔합니다.
const Expenses = props => {
let expensesContent = <p>No expenses found.</p>;
if (filteredExpenses.length > 0) {
expensesContent = filteredExpenses.map(expense => (
<ExpenseItem
key={expense.id}
title={expense.title}
amount={expense.amount}
date={expense.date}
/>
));
}
return { expensesContent };
};
간략한 형변환 팁
Number 형으로 바꿀 때 앞에 + 붙이기
String 으로 바꿀 때 뒤에 + ’’ 붙이기
Styling Components
리엑트에서 요소를 스타일링 하는 방법은 세가지가 있습니다. 첫번째로는 기본 css를 사용하는 것이고 , Styled Components, CSS Module 입니다.
기본 CSS
#goals {
width: 35rem;
max-width: 90%;
margin: 3rem auto;
}
#goal-form {
width: 30rem;
max-width: 90%;
margin: 3rem auto;
padding: 2rem;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.2);
border-radius: 10px;
}
import "./App.css";
모두가 잘 알법한 기본 방식입니다.
Styled Components
// import - Styled-components를 npm을 통해 다운받아야 합니다.
import styled from './styled-components';
// 선언
const Button = styled.button`
width: 100%;
font: inherit;
padding: 0.5rem 1.5rem;
border: 1px solid #8b005d;
color: white;
background: #8b005d;
box-shadow: 0 0 4px rgba(0, 0, 0, 0.26);
cursor: pointer;
@media (min-width: 768px) {
width: auto;
}
&:focus {
outline: none;
}
&:hover,
&:active {
background: #ac0e77;
border-color: #ac0e77;
box-shadow: 0 0 8px rgba(0, 0, 0, 0.26);
}
`;
// 호출
<Button>취소</Button>;
호출은 선언한 객체의 이름인 Button을 컨테이너로 사용합니다.
const FormControl = styled.div`
margin: 0.5rem 0;
& label {
font-weight: bold;
display: block;
margin-bottom: 0.5rem;
color: ${props => (props.invalid ? 'red' : 'black')};
}
& input {
display: block;
width: 100%;
border: 1px solid ${props => (props.invalid ? 'red' : '#ccc')};
background-color: ${props => (props.invalid ? '#ffd7d7' : 'transparent')};
font: inherit;
line-height: 1.5rem;
padding: 0 0.25rem;
}
& input:focus {
outline: none;
background: #fad0ec;
border-color: #8b005d;
}
`;
//...
<FormControl invalid={!isValid}>
<label>Course Goal</label>
<input type="text" onChange={goalInputChangeHandler} />
</FormControl>;
Styled Components는 동적 스타일링
이 가능합니다. 위 코드는 invalid라는 props를 만들고 해당 props일 때 css를 동적으로 변경해주는 예시입니다.
CSS Module
// import - 가운데에 module을 꼭 적어줘야 합니다.
import styles from './Button.module.css';
// 호출
const Button = props => {
return (
<button type={props.type} className={styles.button} onClick={props.onClick}>
{props.children}
</button>
);
};
선언은 기본 css와 동일합니다. styles.객체명
의 형식으로 사용합니다.
장단이 있지만 강사님은 CSS Module을 선호한다고 합니다. 그 이유는 js와 css가 분리되는 것도 좋고 기본 CSS의 관행을 따르는 것도 좋기 때문이라고 합니다.
debuging
디버깅 섹션에서 배운것은 react dev tools 입니다. 리엑트를 하면서 컴포넌트 구조와 표출되는 HTML이 달라서 조금 난감했었는데 이런 툴이 있다니..! 앞으로 자주 애용할 것 같습니다.
모호한 점
언제 어떤 값을 state를 사용해야 하는지에 대한 게 헷갈립니다. 동적으로 변하는 값을 state로 두어 state값이 업데이트가 되면 리랜더링을 해주는건 알겠는데… 써야하는지 상위에 써야하는지 그냥 사용하지 말아야되는지 헷갈리는 순간들이 있는 것 같습니다. 조금 더 경험해봐야 할 것 같습니다.