레고처럼 조립해나갈 수 있는 부품 단위로 UI 컴포넌트를 만들어 나가는 개발
# Clone the template
npx degit chromaui/intro-storybook-react-template taskbox
cd taskbox
# Install dependencies
yarn
CSS ➡️ SASS ➡️ BEM ➡️ CSS Modules ➡️ Styled Components
구조화된 CSS가 필요하게 된 이유
➡️ CSS 작업을 효율적으로 하기 위한 방법이 필요해짐
방법론들의 공통 지향점
CSS 방법론들의 특징, 장단점
const Button = styled.a`
display: inline-block;
border-radius: 3px;
padding: 0.5rem 0;
margin: 0.5rem 1rem;
width: 11rem;
`;
➡️ JavaScript에서 변수를 선언하듯이 Button 을 만들고, tag의 속성을 정의하고 (여기서는 a tag), back-ticks (``
) 안에 기존 CSS 문법을 이용하여 스타일 속성을 정의해줌.
Styled Component는 화면에 어떤 컴포넌트가 렌더링 되었는지 추적해서 해당하는 컴포넌트에 대한 스타일을 자동으로 삽입한다. 따라서 코드를 적절히 분배해 놓으면 사용자가 어플리케이션을 사용할 때 최소한의 코드만으로 화면이 띄워지도록 할 수 있다.
Styled Component는 스스로 유니크한 className을 생성한다. 이는 className의 중복이나 오타로 인한 버그를 줄여준다.
Styled Component 는 모든 스타일 속성이 특정 컴포넌트와 연결되어 있기 때문에 만약 컴포넌트를 더 이상 사용하지 않아 삭제할 경우 이에 대한 스타일 속성도 함께 삭제된다. (찾을 필요 ㄴㄴ)
className을 일일이 수동으로 관리할 필요 없이 React 의 props 나 전역 속성을 기반으로 컴포넌트에 스타일 속성을 부여하기 때문에 간단하고 직관적이다.
컴포넌트에 스타일을 상속하는 속성을 찾아 다른 CSS 파일들을 검색하지 않아도 되기 때문에 코드의 크기가 커지더라도 유지보수가 어렵지 않다.
개별 컴포넌트마다 기존의 CSS 를 이용하여 스타일 속성을 정의하면 된다. 이외의 것들은 Styled Component 가 알아서 처리해 준다.
# with npm
$ npm install --save styled-components
# with yarn
$ yarn add styled-components
Styled Component 에서는 package.json에 다음 코드를 추가하도록 권장하고 있다.
아래의 코드를 추가하면 여러 버전의 Styled Component가 설치되어 발생하는 문제를 줄여준다.
{
"resolutions": {
"styled-components": "^5"
}
}
예제 코드 1
import "./styles.css";
import styled from "styled-components";
const Button = styled.button`
/* Adapt the colors based on primary prop */
background: ${(props) => (props.primary ? "palevioletred" : "white")};
color: ${(props) => (props.primary ? "white" : "palevioletred")};
font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border: 2px solid palevioletred;
border-radius: 3px;
`;
const Tomato = styled(Button)`
color: tomato;
border-color: tomato;
`;
export default function App() {
return (
<div className="App">
<Button>Normal</Button>
<Button primary>Primary</Button>
<Tomato>Tomato</Tomato>
</div>
);
}
예제 코드 2
import styled from "styled-components";
// Styled Component로 만들어진 Input 컴포넌트 입니다.
const Input = styled.input`
padding: 0.5em;
margin: 0.5em;
color: ${(props) => props.inputColor || "red"};
background: papayawhip;
border: none;
border-radius: 3px;
`;
export default function App() {
return (
<div>
{/* 아래 Input 컴포넌트는 styled component인 Input 컴포넌트에 지정된 inputColor(red)가 적용되었습니다. */}
<Input defaultValue="김코딩" type="text" />
{/* 아래 Input 컴포넌트는 props로 전달된 커스텀 inputColor(blue)가 적용되었습니다. */}
<Input defaultValue="박해커" type="text" inputColor="blue" />
</div>
);
}
import React, { useRef } from "react";
const Focus = () => {
const firstRef = useRef(null);
const secondRef = useRef(null);
const thirdRef = useRef(null);
const handleInput = (e) => {
console.log(e.key, e.target);
if (e.key === "Enter") {
if (e.target === firstRef.current) {
secondRef.current.focus();
e.target.value = "";
} else if (e.target === secondRef.current) {
thirdRef.current.focus();
e.target.value = "";
} else if (e.target === thirdRef.current) {
firstRef.current.focus();
e.target.value = "";
} else {
return;
}
}
};
return (
<div>
<h1> 타자연습 </h1>
<h3> 각 단어를 바르게 입력하고 엔터를 누르세요 </h3>
<div>
<label> hello </label>
<input ref={firstRef} onKeyUp={handleInput} />
</div>
<div>
<label> world </label>
<input ref={secondRef} onKeyUp={handleInput} />
</div>
<div>
<label>codestates </label>
<input ref={thirdRef} onKeyUp={handleInput} />
</div>
</div>
);
};
export default Focus;
import { useRef } from "react";
export default function App() {
const videoRef = useRef(null);
const playVideo = () => {
videoRef.current.play();
};
const pauseVideo = () => {
videoRef.current.pause();
};
return (
<div className="App">
<div>
<button onClick={playVideo}>Play</button>
<button onClick={pauseVideo}>Pause</button>
</div>
<video ref={videoRef} width="320" height="240" controls>
<source
type="video/mp4"
src="https://player.vimeo.com/external/544643152.sd.mp4?s=7dbf132a4774254dde51f4f9baabbd92f6941282&profile_id=165"
/>
</video>
</div>
);
}