앞에서 component에 대해서 다루면서 component에 CSS를 입히는 방법에 대해서 같이 이야기했다.
이번에는 동적 할당에 대해서 알아보자.
How to set style Dynamically
React로 만들어진 웹 앱들은 대체로 화려하다.
이는 사용자의 상호작용에 맞춰 페이지도 반응하기 때문인데, 이렇게 반응하기 위해서는 정적(static)으로 style을 입혀서는 안된다.
동적으로 style하는 방법에는 몇 가지가 존재하는데 차근차근 알아보자
using style[property]
HTML 내장 요소에 inline CSS로 입력한다.
style은 HTML 기본 요소이기는 하지만 React에서 약간 다르게 작동한다.
style 요소를 활용하여 정적으로 CSS를 입히는 경우에는 다음과 같은 구조로 사용한다.
// In JSX, static styling
<div style={"height: 10%"}></div>
다음의 규칙에 맞게 사용해야한다.
- style={}과 같은 형식으로 중괄호{}에 값을 입력한다.
- key 값은 문자열이 아니어도 상관없지만, hyphen(-)이 있는 경우에는 문자열로 감싸주거나 camelCase 형식으로 써야한다.
- background-color를 예로 들면, 'background-color'나 backgroundColor로 사용해야한다.
- hyphen(-)이 들어간 그대로 사용한다면 유효하지 않은 property 이름이 되기 때문이다.
- 중괄호{}에 들어가는 값은 JavaScript 형식으로 CSS를 사용해야한다.
- 해당 객체에 대해서 key 값은 CSS property 이름을, value로는 key에 맞는 value를 사용해야한다.
하지만 특정 변수를 JSX 코드에 입력할 때에는 중괄호{}를 사용했던 것을 기억할 것이다.
그렇다. style 요소에 동적으로 스타일링 하기 위해서는 이중 중괄호{{}}에 다음과 같이 값을 넣어줘야한다.
// 여기서 barFillHeight는 props로 받아온 값에 따라 크기 변함.
<div style={{ height: barFillHeight }} ></div>
using State on inline CSS
마찬가지로 state를 활용하여 inline CSS를 바꿀 수 있다.
const CourseInput = (props) => {
const [enteredValue, setEnteredValue] = useState("");
const [isValid, setIsValid] = useState(true);
const goalInputChangeHandler = (event) => {
if(event.target.value.trim().length > 0){
setIsValid(true) ;
}
setEnteredValue(event.target.value);
};
const formSubmitHandler = (event) => {
event.preventDefault();
if (enteredValue.trim().length === 0) {
setIsValid(false);
return;
}
props.onAddGoal(enteredValue);
};
return (
<form onSubmit={formSubmitHandler}>
<div className="form-control">
<label style={{ color: !isValid ? "red" : "black" }}>Course Goal</label>
<input
type="text"
style={{
borderColor: !isValid ? "red" : "black",
background: !isValid ? "salmon" : "transparent",
}}
onChange={goalInputChangeHandler}
/>
</div>
<Button type="submit">Add Goal</Button>
</form>
);
};
해당 코드를 잠깐 살펴보자면 isValid라는 값을 state로 설정하여 오류가 발생했을 때 전반적인 form의 색깔을 빨간색으로 변경해주는 코드다.
이러한 접근 방식으로는 항상 inline style을 사용해야 해서 CSS 우선순위 최상단에 위치한다.
따라서 CSS class로 적용한 style들은 모두 override되어 무시되며 기존의 상태로 돌아가기 위해서는 새로고침을 할 수 밖에 없다.
using state on class CSS
className을 통해 정적으로 style을 입히는 경우, HTML 내장 요소에 className="using-class-name"
과 같이 사용해주었다. CSS class를 여러개 제작하여 State로 동적으로 값을 변경해주면 된다.
/* 'form-control'클래스를 가지고 있으면서 'invalid'클래스를 가지고 있는 태그의 하위 input tag*/
.form-control.invalid input {
border-color: red;
background: #ffd7d7;
}
/* 'form-control'클래스를 가지고 있으면서 'invalid'클래스를 가지고 있는 태그의 하위 label tag*/
.form-control.invalid label {
color: red ;
}
import React, { useState } from "react";
import Button from "../../UI/Button/Button";
import "./CourseInput.css";
const CourseInput = (props) => {
const [enteredValue, setEnteredValue] = useState("");
const [isValid, setIsValid] = useState(true);
const goalInputChangeHandler = (event) => {
if (event.target.value.trim().length > 0) {
setIsValid(true);
}
setEnteredValue(event.target.value);
};
const formSubmitHandler = (event) => {
event.preventDefault();
if (enteredValue.trim().length === 0) {
setIsValid(false);
return;
}
props.onAddGoal(enteredValue);
};
return (
<form onSubmit={formSubmitHandler}>
<div className={`form-control ${!isValid ? "invalid" : ""}`}>
<label>Course Goal</label>
<input type="text" onChange={goalInputChangeHandler} />
</div>
<Button type="submit">Add Goal</Button>
</form>
);
};
export default CourseInput;
위의 코드를 살펴보자면, inline CSS의 class버전이라고 볼 수 있다.
이전의 깨끗하지 않았던 코드들이 깔끔하게 정리된 모습이다.
여기서 자세히 봐야할 부분이 있는데 Template literals(`)이다.
싱글 따옴표(')도 아닌 이 문자는 JavaScript에서 둘러 쌓인 것을 일반적인 문자열로 취급한다.
기존 class에 ${}를 추가해서 JSX 코드를 작성하는 것과 마찬가지로 활용할 수 있다.
따라서 해당 코드는 isValid가 true일 때, class '.invalid'를 추가해주는 코드로 해석된다.
이런 방법으로 CSS 파일로 class만으로도 작업할 수 있게 되었다.