동적으로 스타일 변경
- 상태변수를 사용하여 동적으로 관리
- 입력값 검증해서 동적 스타일 변경
const CourseInput = ({ onAdd }) => {
const [enteredText, setEnteredText] = useState('');
const [isValid, setIsValid] = useState(true);
const formSubmitHandler = e => {
e.preventDefault();
if (enteredText.trim().length === 0) {
setIsValid(false);
return;
}
const newGoalObject = {
id: Math.random().toString(),
text: enteredText
};
onAdd(newGoalObject);
setEnteredText('');
};
const goalChangeHandler = e => {
const inputValue = e.target.value;
if (inputValue.trim().length > 0) {
setIsValid(true);
}
setEnteredText(inputValue)
}
return (
<div className="form-control">
<label>나의 목표</label>
<input
type="text"
onChange={goalChangeHandler}
value={enteredText}
style={{
backgroundColor: isValid ? 'transparent' : 'red',
borderColor: isValid ? 'black' : 'red',
}}
/>
export default CourseInput;
클래스 조작하여 동적 스타일 변경 (더 쉬움)
return (
<form onSubmit={formSubmitHandler}>
<div className={`form-control ${isValid ? '' : 'invalid'}`}>
<label>나의 목표</label>
<input
type="text"
onChange={goalChangeHandler}
value={enteredText}
/>
</div>
<Button type="submit" >목표 추가하기</Button>
</form>
);
1. Styled-Components
- 클래스 이름을 무작위로 생성하게 해주어서 협업 시 클래스 이름의 충돌을 방지 해준다.
- css 파일 따로 만들지 않아도 됨.
- props를 통해 컴포넌트의 스타일을 조건부로 변경 가능
import React from "react";
import styled from "styled-components";
const Button = styled.button`
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;
&:focus {
outline: none;
}
&:hover,
&:active {
background: #ac0e77;
border-color: #ac0e77;
box-shadow: 0 0 8px rgba(0, 0, 0, 0.26);
}
`;
export default Button;
2. CSS Module
- 각 컴포넌트에 대해 고유한 클래스 이름을 생성하여 스타일 충돌을 방지하
이를 통해 CSS를 모듈화하여 각 컴포넌트에서 독립적으로 사용할 수 있게 해줌
- 기존 css 파일명을 xxx.module.css로 변경
import React from 'react';
import styles from './CourseItem.module.css';
const CourseItem = ({ item, onDelete }) => {
const deleteHandler = e => {
console.log('삭제 해줘');
onDelete(item.id);
}
return <li className={styles['goal-item']} onClick={deleteHandler}>{item.text}</li>;
};
export default CourseItem;
React Portal
- 모달의 종속성을 없애고, 전역에서 쓸 수 있도록 portal을 활용하는 방법
- index.html
- 기존엔 div#root만 존재했지만, 두개의 div를 추가
<div id="root"></div>
<!-- Modal의 내용이 들어갈 위치 -->
<div id="overay-root"></div>
<!-- Backdrop의 내용이 들어갈 위치 -->
<div id="backdrop-root"></div>
- ErrorModal.js에서 컴포넌트를 따로 빼서 작성 후,
ReactDOM을 import 하고, createPortal() 함수를 사용
{ createPortal(보낼 컴포넌트, 컴포넌트를 전달할 노드 요소) }
import React from 'react';
import ReactDOM from 'react-dom';
import Card from '../Card';
import Button from '../Button';
import styles from './ErrorModal.module.css';
const BackDrop = ({ onClose }) => {
return (
<div
className={styles.backdrop}
onClick={onClose}
></div>
);
};
const ModalOverlay = ({ title, message, onClose }) => {
return (
<Card className={styles.modal}>
<header className={styles.header}>
<h2>{title}</h2>
</header>
<div className={styles.content}>
<p>{message}</p>
</div>
<footer className={styles.actions}>
<Button onClick={onClose}>Okay</Button>
</footer>
</Card>
);
};
const ErrorModal = ({ title, message, onClose }) => {
return (
<>
{
ReactDOM.createPortal(
<BackDrop onClose={onClose} />
, document.getElementById('backdrop-root')
)
}
{
ReactDOM.createPortal(
<ModalOverlay title={title} message={message} onClose={onClose} />
, document.getElementById('overay-root')
)
}
</>
);
};
export default ErrorModal;
useRef
- DOM에 직접 접근하지 않고 조작할 수 있게함
import React, { useRef } from 'react';
const MyComponent = () => {
const myInputRef = useRef();
const focusInput = () => {
myInputRef.current.focus();
};
return (
<div>
<input ref={myInputRef} type="text" />
<button onClick={focusInput}>Focus the input</button>
</div>
);
};
export default MyComponent;
- input 요소를 myInputRef에 연결 -> 그러면 myInputRef.current는 input요소를 가리킴 -> focusInput 함수에서 myInputRef.current.focus();를 호출하면, 이 input 요소에 focus가 가게됨