Dynamic Styling | Validation
form을 제출하는 이벤트가 발생했을 때, 사용자가 input에 입력한 값의 유효성에 따라 스타일링에 변화를 줄 수 있다. 유효한 값을 제출하면 input의 border를 초록색으로, 그렇지 않으면 빨간색으로 보여주는 것이 가장 대표적이다.
inline style
const CourseInput = (props) => {
const [enteredValue, setEnteredValue] = useState('');
const [isValid, setIsValid] = useState(true);
const goalInputChangeHandler = (event) => {
setEnteredValue(event.target.value);
};
const formSubmitHandler = (event) => {
event.preventDefault();
if (enteredValue.trim().length === 0) {
setIsValid(false);
return;
} else {
setIsValid(true);
props.onAddGoal(enteredValue);
setEnteredValue('');
}
};
return (
<form onSubmit={formSubmitHandler}>
<div className='form-control'>
<label style={{ color: !isValid ? 'red' : '' }}>Course Goal</label>
<input
style={{
border: !isValid ? '1px solid red' : '1px solid black',
backgroundColor: !isValid ? 'salmon' : '',
}}
type='text'
onChange={goalInputChangeHandler}
value={enteredValue}
/>
</div>
<Button type='submit'>Add Goal</Button>
</form>
);
};
- isValid | 유효성 검사 결과에 따라 re-rendering이 일어나야 하므로, state로 관리한다.
- input
- style | style property는 {js 구문} 안에서 {객체}로 전달된다. => {{ }}
- key | camelCase
- value | ternary operator를 이용해 적용할 스타일링을 동적으로 설정할 수 있다.
- value | 2 way biding, input 태그에서도 value 속성 값을 연결해야 input이 초기화된다.
- style | style property는 {js 구문} 안에서 {객체}로 전달된다. => {{ }}
- inline styling에 적용되어 있는 스타일은 최우선 순위가 된다. 만약 css 파일에서 border의 default color를 다른 값으로 지정했더라도, inline style이 그 값을 덮어 쓴다. => className을 동적으로 설정해서 스타일링 하는 것이 더 좋다.
dynamic className
<form onSubmit={formSubmitHandler}>
<div className={`form-control ${!isValid ? 'invalid' : ''}`}>
<label>Course Goal</label>
<input
type='text'
onChange={goalInputChangeHandler}
value={enteredValue}
/>
</div>
<Button type='submit'>Add Goal</Button>
</form>
- <div className={ 'form-control ' + !isValid ? 'invalid' : ' ' }>
- ??? 템플릿 리터럴을 사용하지 않고 위와 같이 작성했더니 className의 form-control 부분 설정이 안됨
CSS module
컴포넌트에 개별적으로 css를 import 한다고 해서, 자동으로 스타일링이 모듈화되는 것은 아니다. 즉 작성된 스타일링이 컴포넌트에 관계없이 전역(global scope)에서 적용된다. 그렇기 때문에 className을 지정할 때, 다른 컴포넌트의 className과 겹치지 않도록 신경써야 했다. 그래서 개발자 대신 유니크한 className을 지정해 주는 라이브러리가 등장했다.
3rd party library | styled component package
import styled from 'styled-components';
const Button = styled.button`
font: inherit;
padding: 0.5rem 1.5rem;
color: ${props => props.isValid ? 'red' : 'black'};
cursor: pointer;
width:100%;
& span {
color: red;
}
&:focus {
outline: none;
}
&:hover,
&:active {
background: #ac0e77;
}
@media screen and (min-width:768px) {
width: auto;
}
`;
export default Button;
- styled.HTMLElement` ` | style 객체는 HTML 요소를 만드는 메서드를 가지고 있다. styled.h1, styled.div 등과 같이 사용할 수 있다. `backtick` 안에 함수의 인자를 전달할 수 있는데, ()와는 조금 다르게 동작한다(js taggled template literal).
- style components는 고유한 className을 만들어서, 인자로 전달한 스타일링을 적용한다.
- 여전히 css를 전역에서 사용하기는 하지만, 사용자가 스타일링이 겹치지 않도록 className을 지정해야 하는 수고를 덜어준다.
- HTML요소를 만들 때 props으로 전달받는 값을 연결 하기 때문에, 따로 props에 대해 설정하지 않더라도 다음과 같이 사용할 수 있다.
- <Button type='submit' isValid={...}>Add Goal</Button>
- 만약 className을 props으로 전달하면, 만들어지는 고유한 클래스에 전달받은 class를 추가하는 방식으로 동작한다. => dynamic class를 사용할 수 있다.
- html에서 사용하는 default 속성 뿐만 아니라, 사용자가 지정하는 props을 전달할 수도 있다. => backtick 안에서 props 접근할 수 있다.
- media query도 이용할 수 있다.
- selector를 설정하지 않아도 된다.
하나의 컴포넌트에서 styled component 여러 개 적용하기
import Button from '../UI/Button';
create react app | CSS module
import styles from './Button.module.css'; // Import css modules stylesheet as styles
// import './Button.css'; Import regular stylesheet
const Button = props => {
return (
// className={`${styles.button} ${!isValid && styles.inValid}`}
<button type={props.type} className={styles.button} onClick={props.onClick}>
{props.children}
</button>
);
};
export default Button;
- styles | module.css 파일에서 styles라는 이름으로 객체를 import 한다.
- styles.button 또는 styles['button'] | className은, string이 아니라 styles 객체의 프로퍼티로 지정한다.
- module.css는 코드가 브라우저에서 실행되기 전에, 우리가 지정한 className을 유니크한 값으로 변환해 준다.
- 여러 개의 css 파일에서 같은 className으로 스타일링 하더라도, 코드가 실행되기 전에 아래와 같은 형식으로 유니크하게 변환된다.
- Button_button_id | HTMLElement, 우리가 지정한 클래스 이름, 해쉬코드로 이루어져 있다.
- css에서 사용하는 문법을 그대로 적용한다.
'Study > React' 카테고리의 다른 글
useRef (0) | 2022.06.18 |
---|---|
Fragment & Portal (0) | 2022.06.18 |
Conditional contents (0) | 2022.06.17 |
Dynamic List (0) | 2022.06.17 |
prevState (0) | 2022.06.16 |