JiSoo's Devlog
[Udemy React 완벽 가이드] Section 6 본문
동적 인라인 스타일 설정하기
- trim 메소드는 시작이나 끝부분에 과도하게 쓰인 공백을 제거해 주는 메소드
- trim 메소드를 사용한 이유는 사용자가 수많은 공백을 입력한 경우 배제하기 위해서이다
- enteredValue.trim().length === 0 은 입력되는 값이 비었다는 것을 알려준다
- 유효하지 않은 값을 입력해 줬을 때 어떤 스타일을 적용하고 싶다면 state를 사용하면 되는데 state는 사용자가 제출했는지 입력한 것이 유효한지를 나타내는 지표가 된다
- 가장 쉬운 방법은 레이블에 inline 스타일을 적용해 주는 방법인데 inline 스타일 props는 값으로 객체를 갖는다
- 그 객체에서 이 컴포넌트를 위해 이 요소에 설정할 수 있는 자바스크립트에 있는 다양한 css 스타일의 속성을 목표로 한다
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;
}
props.onAddGoal(enteredValue);
};
return (
<form onSubmit={formSubmitHandler}>
<div className="form-control">
<label style={{ color: !isValid ? "red" : "black" }}>Course Goal</label>
<input
style={{
bordeColor: !isValid ? "red" : "black",
background: !isValid ? "salmon" : "transparent",
}}
type="text"
onChange={goalInputChangeHandler}
/>
</div>
<Button type="submit">Add Goal</Button>
</form>
);
};
style={{ color: !isValid ? "red" : "black" }}
- 단지 입력값이 유효하지 않은 경우에 조건부로 특정 스타일을 설정하기 때문에 inline 스타일로 덮어쓰는 것이다
- inline 스타일이 최우선 순위를 차지하기 때문에 만족스럽지 않다
- 리셋 기능 작업 ▼
const goalInputChangeHandler = (event) => {
if (event.target.value.trim().length > 0) {
setIsValid(true);
}
setEnteredValue(event.target.value);
};
동적 스타일 연습
import React, { useState } from 'react';
export default function App() {
const [isValid, setIsValid] = React.useState(false);
const clickHandler =()=> {
setIsValid(isValid => !isValid);
}
return (
<div>
<p style={{color: isValid ? 'red' : 'white'}}>Style me!</p>
<button onClick={clickHandler}>Toggle style</button>
</div>
);
}
동적으로 CSS 클래스 설정하기
- form-control이 invalid 클래스에 접근 가능하다고 선언할 수 있는데 이 말은 같은 요소에 있어야 된다는 뜻이며 이때 form-control과 invalid 사이에 공백이 없어야 한다
.form-control.invalid input {
border-color: red;
background: rgb(255, 215, 215);
}
.form-control.invalid label {
color: red;
}
- 이 css가 효과를 가지려면 invalid 클래스가 동적으로 추가되어야 한다
- 동적인 값을 지정해 주기 위해 중괄호 사용
- ` ` 을 사용해 주는데 이것은 싱글 따옴표가 아닌 백틱이 있는 문자열을 구성한다
- 백틱 사이에 있는 것들은 일반적인 문자열로 취급될 것이다
- 문자열에 동적인 값을 주입할 수도 있다 -> ${ } 이 중괄호 속 모든 콘텐츠는 자바스크립트 표현식이 될 수 있다
<div className={`form-control ${!isValid ? 'invalid' : ''}`}>
- 클래스 이름이 form-control 뒤에 아무것도 없거나 form-control invalid가 될 것이다
동적 CSS 클래스 연습
import React, {useState} from 'react';
export default function App() {
const [isValid,setIsValid] = React.useState(false);
const clickHandler =()=> {
setIsValid(isValid=>!isValid)
}
return (
<div>
<p className={ isValid ? "active" : ""}>Style me!</p>
<button onClick={clickHandler}>Toggle style</button>
</div>
);
}
Styled Components 소개
- DOM 요소 어딘가에 같은 이름의 클래스를 갖고 있다면 영향을 미치게 된다
- 응용 프로그램의 다른 위치에서 사용되는 것을 막기 위한 방법 2가지가 있다
- 첫 번째 방법은 styled components 패키지를 사용하는 것
- styled components는 특정 스타일이 첨부된 컴포넌트를 구축할 수 있도록 도와주는 패키지인데 이 스타일이 첨부되는 컴포넌트에만 영향을 미치고 다른 컴포넌트에는 전혀 영향을 미치지 않는다
import React from 'react';
import styled from 'styled-components';
const Button = styled.button``;
export default Button;
- styled.button``; 이 구문은 태그드 템플릿 리터럴이라고 부르는데 자바스크립트의 기본 기능으로 어떤 프로젝트에서도 사용 가능하다
- 여기서 button은 styled 객체의 메소드이다
- 백틱에 전달하는 것은 특별한 방식으로 이 메소드에 전달될 것이다
- 백틱에 우리가 전달하는 것이 결국 Button 메소드로 간다는 것만 알면 된다
- button 메소드가 새로운 button 컴포넌트를 반환한다
- styled 패키지는 모든 html 요소에 대한 메소드를 갖고 있다.
- 단락을 위한 p메소드와 h1, h2 태그를 위한 h1, h2 그리고 div를 생성하기 위한 div 등이 있다
- 전체 표현식은 button을 반환하지만 백틱 사이에 전달한 스타일이 있는 button 일 것이다
- 백틱 구문을 여러 줄의 문자열을 작성할 수 있다는 장점이 있다
- 백틱 사이에 전달할 스타일이 button에 직접적으로 영향을 줄 것이다
- 그렇기 때문에 선택자를 삭제하고 스타일을 붙여 넣으면 그것들은 button 메소드가 호출되어 반환하는 button 요소에 추가되고 상수 button까지 영향을 미칠 것이다
- styled components에서 제공하는 &를 사용하면 되는데 이것은 여기서 생성한 이 컴포넌트에 대해 이 경우에 특별한 가상 선택자를 사용하겠다고 패키지에게 선언하는 것이다 -> &:hover , &:active (button:hover, button:active)
- react 임포트 구문은 삭제해도 된다 - JSX 구문을 이제 사용하지 않기 때문에
- 모든 클래스는 고유한 이름을 가지기 때문에 앱에 있는 다른 컴포넌트에 영향을 주지 않는다
Styled Components & 동적 Props
- 파일에서 다른 컴포넌트에도 사용되는 컴포넌트를 갖고 있다면 동일한 파일에서 그 두 컴포넌트를 가질 수도 있다
- &는 항상 생성된 컴포넌트를 다시 참조한다
CourseInput.js
import React, { useState } from "react";
import styled from "styled-components";
import Button from "../../UI/Button/Button";
import "./CourseInput.css";
const FormControl = styled.div`
margin: 0.5rem 0;
& label {
font-weight: bold;
display: block;
margin-bottom: 0.5rem;
}
& input {
display: block;
width: 100%;
border: 1px solid #ccc;
font: inherit;
line-height: 1.5rem;
padding: 0 0.25rem;
}
& input:focus {
outline: none;
background: #fad0ec;
border-color: #8b005d;
}
&.invalid input {
border-color: red;
background: rgb(255, 215, 215);
}
&.invalid label {
color: red;
}
`;
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}>
<FormControl className={!isValid && "invalid"}>
<label>Course Goal</label>
<input type="text" onChange={goalInputChangeHandler} />
</FormControl>
<Button type="submit">Add Goal</Button>
</form>
);
};
export default CourseInput;
- 일부 props에 따라 스타일을 동적인 방식으로 바꿀 수 있다
- props가 유효한지 체크해서 유효하지 않을 때와 유효할 때 스타일 지정
import React, { useState } from "react";
import styled from "styled-components";
import Button from "../../UI/Button/Button";
import "./CourseInput.css";
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: ${(props) => (props.invalid ? "#ffd7d7" : "transparent")};
font: inherit;
line-height: 1.5rem;
padding: 0 0.25rem;
}
& input:focus {
outline: none;
background: #fad0ec;
border-color: #8b005d;
}
`;
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}>
<FormControl invalid={!isValid}>
<label>Course Goal</label>
<input type="text" onChange={goalInputChangeHandler} />
</FormControl>
<Button type="submit">Add Goal</Button>
</form>
);
};
export default CourseInput;
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;
}
CSS 모듈 사용하기
- css 모듈을 사용하고 싶다면 css 파일을 임포트 할 때 styles나 classes를 임포트 해준다
- 화면 뒤에서 벌어지는 코드 변환을 위해 css 파일 이름을 바꿔줘야 한다 -> Button.module.css
- 파일 이름 바꿔주는 것은 기본적으로 css 모듈이 작동하도록 코드를 변환하라고 컴파일 프로세스에게 보내는 신호이다
- 버튼 클래스명을 {styles} 동적인 값으로 주는데 이것은 객체이며 그 객체 안에 파일에서 프로퍼티로 정의하는 모든 클래스를 갖는다. 그래서 css 파일에 button 클래스를 추가했다면 button 프로퍼티를 갖게 되는 것이다
className={styles.button}
- css 클래스나 css 파일을 가지고 그 클래스 이름을 기본적으로 고유하게 바꾸는 일을 한다
- 모든 컴포넌트에 대해 임포트하고 있는 모든 클래스의 이름을 바꾸기 때문에 모든 css 파일을 고유하게 만든다
- 고유한 버전의 스타일과 클래스 생성
- css 모듈의 개념은 css 파일에서 설정한 css 스타일의 범위가 이 파일을 임포트 하는 컴포넌트에 한정된다
- 임포트 된 스타일 객체의 클래스에 속성으로 접근하기 때문에 css 파일로 작업
import React from "react";
import styles from "./Button.module.css";
const Button = (props) => {
return (
<button type={props.type} className={styles.button} onClick={props.onClick}>
{props.children}
</button>
);
};
export default Button;
CSS 모듈을 사용한 동적 스타일
- form-control은 유효하지 않은 프로퍼티 이름인데 프로퍼티에 접근하기 위해 대괄호와 따옴표로 이름을 감싸주면 된다 -> 문자열은 자바스크립트 객체에서 유효한 키이기 때문에
- 중간에 대시(-)가 없는 다른 css 클래스 이름을 선택할 수도 있다
- 변환된 invalid 클래스 버전을 추가하려면 백틱구문으로 돌아가 입력할 값에 문자열을 생성할 수 있다
- 첫 번째 입력할 값은 변환된 클래스 이름을 입력하는데 이것은 스타일 객체에서 이 문자열로 추출한 것이다
return (
<form onSubmit={formSubmitHandler}>
<div
className={`${styles["form-control"]} ${!isValid && styles.invalid}`}
>
<label>Course Goal</label>
<input type="text" onChange={goalInputChangeHandler} />
</div>
<Button type="submit">Add Goal</Button>
</form>
);
- styled 컴포넌트와 다른 중요한 점은 css에서는 선택자가 필요하다
@media (min-width: 768px) {
.button {
width: auto;
}
}
728x90
'Frontend > React' 카테고리의 다른 글
[Udemy React 완벽 가이드] Section 8 (2) | 2024.01.04 |
---|---|
[Udemy React 완벽 가이드] Section 7 (1) | 2024.01.04 |
[Udemy React 완벽 가이드] Section 5 (2) | 2024.01.04 |
[Udemy React 완벽 가이드] Section 4 (2) | 2024.01.04 |
[Udemy React 완벽 가이드] Section 3 (1) | 2024.01.04 |