styled-component를 사용하기 전에 이것을 왜 만들었는지 알아보자. 무언가를 사용할 때 제대로 모르고 사용하는 게 습관이 되다보면 오류의 원인을 파악하기 어려워지기 때문이다.
공식문서에 따르면 styled-component는 리액트 컴포넌트의 CSS스타일링을 편하게 하기위해 만들어졌다고 한다.
styled-component는 제공되는 여러 기능이 있다. 다른 기능들은 체감되지 않아서 잘 모르겠지만, 테마나 props를 사용해 스타일을 간편하게 관리할 수 있다는 것, 이 컴포넌트의 스타일이 어느 CSS파일에 적혀있는지 번거롭게 찾지 않아도 되서 편리하다.
터미널에 입력한다.
//npm
npm install --save styled-components
//yarn
yarn add styled-components
우리가 만드는 styled-component의 이름은 PascalCase로 작성해주는 것이 좋다. 결국 컴포넌트의 한 종류니 기본 html 태그와 헷갈리지 않기 위함이다.
아래와 같은 형식으로 작성해서 사용한다.
아래는 출력 결과이다.
우리가 만드는 styled-component의 내부 CSS 속성에는 함수를 전달해줄 수 있다.
컴포넌트를 잘 보면 태그(h1)옆에 백틱으로 모든 CSS속성들이 감싸져있다(=템플릿 리터럴). 따라서 함수를 전달해주고 싶다면 템플릿 리터럴의 표현식 삽입 형태 ${}
로 전달한다.
css가 섞여있어서 잘 파악하기 어려웠을 수도 있지만, 아래 코드를 봐보자.
const name = '빡세';
console.log(`안녕하세요. ${name}님.`);
백틱을 사용하는 템플릿 리터럴 표현식과 동일한 형태라고 생각하면된다. 안녕하세요
대신에 height: 20px
같은 것들이 들어가 있는거고, ${name}
대신에 ${(props) => props.color}
가 들어가 있는 것과 똑같다.
버튼을 만들어보자. 이 버튼에는 on이라는 state가 존재한다. on이 있으면 버튼에 색을 주고, 없다면 흰색으로 만들자.
props에 값을 담아 전달해보자. 그리고 이 값을 컴포넌트 내부에서 사용해보자. 이렇게 컴포넌트를 만들면 매번 컴포넌트가 적힌 곳으로 돌아가 속성을 수정하거나, 다른 컴포넌트로 분리할 필요가 없이 하나의 컴포넌트로 여러가지로 다른 스타일의 컴포넌트를 만들 수 있다.
styled-component를 상속해서 또 다른 컴포넌트를 만들 수 있다. 만들었던 컴포넌트의 속성들을 다 상속받고, 새로운 속성은 추가하는 방식이다.
: CSS 속성을 적용할 요소를 선택하기 위한 도구다.
styled-component 내부에서도 선택자를 사용할 수 있다.
&는 현재 컴포넌트의 모든 인스턴스를 의미한다. 쉽게 말하면 현재의 컴포넌트(예제에서는 Thing)를 의미한다고 보면 된다. 이걸 사용하고 말고의 차이는 다음과 같다.
&.something = 현재 컴포넌트에서 'something' 클래스명을 갖고있는 것
.something = 현재 컴포넌트 하위(자손)에 'something' 클래스명을 갖고있는 것
사용법을 알아보자. 선택자 아래에 어떤 컴포넌트에 적용되는지 주석으로 적어두었다.
위 예제를 유심히 보면 Input 컴포넌트가 신기하게 const Input = styled.input.attrs({ type: "checkbox" })``;
로 만들어진게 있다. 무슨 문법인지는 모르겠지만 '체크박스가 있는 인풋 태그'라는 것을 추측할 수 있다.
예제에서 사용한 Input은 모두 체크박스 속성을 갖고 있는데, 이렇게 정적인 props(type, size 따위의 것들)를 모두 전달해줄거라면 .attrs 생성자를 사용해보자. 그러면 매 컴포넌트 작성마다 귀찮게 props로 type='checkbox'를 써주지 않아도 된다.
.attrs 생성자는 함수도 인수로 받을 수 있다. 이때 받아오는 props는 컴포넌트에 작성된 props와 동일하다.
그리고 attrs로 만든 컴포넌트도 상속해서 또 다른 컴포넌트로 만들 수 있다. 이 새로만드는 컴포넌트도 atter 생성자를 사용할 수 있는데, 이때 같은 속성에 대해 다른 값을 설정한다면 덮어쓰기된 것 처럼 동작한다.
썸네일에 그림이 너무 예뻐요!