소영 : 베이직 1~8번, 심화 2~3번
현지 : 베이직 9~12번, 심화 1번
Basics
Styled-Components를 사용하는 이유
styled-components는 JavaScript의 태그가 지정된 템플릿 리터럴과 CSS의 기능을 사용해, 컴포넌트에 반응하는 스타일을 제공하는 CSS-in-JS 스타일링을 위한 프레임워크이다.
스타일드 컴포넌트는 리액트 컴포넌트를 스타일링하기 위한 CSS를 향상하기 위해 존재한다. 이는 단일 사용 사례에 집중함으로써 개발자의 경험과 유저가 보는 화면을 최적화하기 위함이다.
styled-components가 제공하는 것
•
자동 critical CSS: styled-components 는 페이지에 렌더링되는 구성 요소를 추적하고 해당 스타일만 자동으로 주입한다. code splitting과 결합하면 사용자가 필요로 하는 최소한의 코드를 로드할 수 있다.
•
클래스명 오류 절감 : styled-components는 스타일에 대해 고유한 클래스 네임을 생성한다. 중복, 겹침, 스펠링 오류에 대해 걱정하지 않아도 된다.
•
쉬운 CSS 삭제 : 그냥 CSS를 사용할 때는 클래스 이름이 코드 어디에서 사용되는지 알기 어려울 수 있지만, styled-components는 모든 스타일링이 특정 컴포넌트와 묶여 있기 때문에 명시적이다. 만약 컴포넌트가 사용되지 않거나 삭제되는 경우에는 모든 스타일도 함께 삭제된다.
•
간단한 동적 스타일링 : 수십 개의 클래스를 수동으로 관리할 필요 없이, props 또는 전역 테마를 기반으로 컴포넌트의 스타일을 조정하는 것이 간단하고 직관적이다.
•
손쉬운 유지 관리 : 컴포넌트에 영향을 주는 스타일을 찾기 위해 여러 파일을 뒤질 필요가 없으므로, 코드베이스가 아무리 크더라도 유지 관리가 쉽다.
•
자동 vendor prefixing : CSS를 현재 표준에 맞게 작성하고 나머지는 스타일 컴포넌트가 처리하도록 한다.
+ styled-components의 장점
1.
CSS 파일을 열 필요 없이 JS 파일에서 바로 스타일을 넣을 수 있다. (CSS-in-JS)
2.
컴포넌트에 적은 스타일이 다른 JS 파일로 오염되지 않는다.
3.
컴포넌트에 적은 스타일은 html 페이지의 <style> 태그에 넣어서 페이지 로딩 시간이 단축된다.
4.
CSS 파일에서 다른 JS 파일에 간섭하지 않는 ‘모듈화’ 기능을 제공한다. (모듈성)
a.
컴포넌트명.module.css 로 CSS 파일 작명하면 된다.
b.
컴포넌트명.js 파일에서 import해서 쓰면 그 스타일은 컴포넌트명.js 파일에만 적용된다.
c.
CSS의 컴포넌트화로 스타일시트의 파일을 유지보수할 필요가 없다.
5.
props를 재활용할 수 있다.
6.
JavaScript와 CSS 사이의 상수와 함수를 쉽게 공유할 수 있다.
/*(CSS-in-JS의 경우 번들의 크기가 커지고 인터랙션한 페이지일 경우 CSS 파일을 따로 관리하는 방법에 비해 느린 성능을 보여줄 수 도 있다는 단점이 있다.) → “@@한 단점~~이 있지만 $$한 이유로 채택했다” 이런 흐름으로 가야할지?*/
설치법
# npm 사용시
npm install --save styled-components
# yarn 사용시
yarn add styled-components
Plain Text
복사
yarn을 사용할 경우, 주 버전 범위에 해당하는 항목을 추가하는 것이 좋다. 이렇게 하면 프로젝트에 여러 버전의 스타일 컴포넌트가 설치되어 발생하는 류의 문제를 피할 수 있다.
{
"resolutions": {
"styled-components": "^5"
}
}
JSON
복사
package.json
NOTE
Babel plugin도 사용하는 것이 좋다. 더 읽기 쉬운 클래스명, 서버사이드렌더링 호환성, 작은 번들 등과 같은 이점을 제공한다.
시작하기
styled-components는 템플릿 리터럴을 활용해 컴포넌트의 스타일을 지정하고, 컴포넌트와 스타일 간의 매핑을 제거한다.
// <h1>태그와 스타일을 렌더링할 Title 컴포넌트 만들기
const Title = styled.h1`
font-size: 1.5em;
text-align: center;
color: palevioletred;
`;
// <section> 태그와 스타일을 렌더링할 Wrapper 컴포넌트 만들기
const Wrapper = styled.section`
padding: 4em;
background: papayawhip;
`;
// Title과 Wrapper 컴포넌트를 사용
render(
<Wrapper>
<Title>
Hello World!
</Title>
</Wrapper>
);
Hello World!
JavaScript
복사
스타일이 첨부된 래퍼와 타이틀, 두 가지 컴포넌트 만드는 예제
NOTE
CSS규칙은 자동적으로 vendor prefix가 붙고, styled-components 가 이를 처리한다.
스타일드 컴포넌트는 CSS 규칙을 접두사로 지정하기 위해 내부적으로 stylis.js 패키지를 사용한다.
props 기반으로 적용하기
props를 기반으로 적용하기 위해, 스타일컴포넌트의 템플릿 리터럴에 함수를 전달할 수 있다.
Basics
Styled-Components를 사용하는 이유
styled-components는 JavaScript의 태그가 지정된 템플릿 리터럴과 CSS의 기능을 사용해, 컴포넌트에 반응하는 스타일을 제공하는 CSS-in-JS 스타일링을 위한 프레임워크이다.
스타일드 컴포넌트는 리액트 컴포넌트를 스타일링하기 위한 CSS를 향상하기 위해 존재한다. 이는 단일 사용 사례에 집중함으로써 개발자의 경험과 유저가 보는 화면을 최적화하기 위함이다.
styled-components가 제공하는 것
•
자동 critical CSS: styled-components 는 페이지에 렌더링되는 구성 요소를 추적하고 해당 스타일만 자동으로 주입한다. code splitting과 결합하면 사용자가 필요로 하는 최소한의 코드를 로드할 수 있다.
•
클래스명 오류 절감 : styled-components는 스타일에 대해 고유한 클래스 네임을 생성한다. 중복, 겹침, 스펠링 오류에 대해 걱정하지 않아도 된다.
•
쉬운 CSS 삭제 : 그냥 CSS를 사용할 때는 클래스 이름이 코드 어디에서 사용되는지 알기 어려울 수 있지만, styled-components는 모든 스타일링이 특정 컴포넌트와 묶여 있기 때문에 명시적이다. 만약 컴포넌트가 사용되지 않거나 삭제되는 경우에는 모든 스타일도 함께 삭제된다.
•
간단한 동적 스타일링 : 수십 개의 클래스를 수동으로 관리할 필요 없이, props 또는 전역 테마를 기반으로 컴포넌트의 스타일을 조정하는 것이 간단하고 직관적이다.
•
손쉬운 유지 관리 : 컴포넌트에 영향을 주는 스타일을 찾기 위해 여러 파일을 뒤질 필요가 없으므로, 코드베이스가 아무리 크더라도 유지 관리가 쉽다.
•
자동 vendor prefixing : CSS를 현재 표준에 맞게 작성하고 나머지는 스타일 컴포넌트가 처리하도록 한다.
+ styled-components의 장점
1.
CSS 파일을 열 필요 없이 JS 파일에서 바로 스타일을 넣을 수 있다. (CSS-in-JS)
2.
컴포넌트에 적은 스타일이 다른 JS 파일로 오염되지 않는다.
3.
컴포넌트에 적은 스타일은 html 페이지의 <style> 태그에 넣어서 페이지 로딩 시간이 단축된다.
4.
CSS 파일에서 다른 JS 파일에 간섭하지 않는 ‘모듈화’ 기능을 제공한다. (모듈성)
a.
컴포넌트명.module.css 로 CSS 파일 작명하면 된다.
b.
컴포넌트명.js 파일에서 import해서 쓰면 그 스타일은 컴포넌트명.js 파일에만 적용된다.
c.
CSS의 컴포넌트화로 스타일시트의 파일을 유지보수할 필요가 없다.
5.
props를 재활용할 수 있다.
6.
JavaScript와 CSS 사이의 상수와 함수를 쉽게 공유할 수 있다.
/*(CSS-in-JS의 경우 번들의 크기가 커지고 인터랙션한 페이지일 경우 CSS 파일을 따로 관리하는 방법에 비해 느린 성능을 보여줄 수 도 있다는 단점이 있다.) → “@@한 단점~~이 있지만 $$한 이유로 채택했다” 이런 흐름으로 가야할지?*/
설치법
# npm 사용시
npm install --save styled-components
# yarn 사용시
yarn add styled-components
Plain Text
복사
yarn을 사용할 경우, 주 버전 범위에 해당하는 항목을 추가하는 것이 좋다. 이렇게 하면 프로젝트에 여러 버전의 스타일 컴포넌트가 설치되어 발생하는 류의 문제를 피할 수 있다.
{
"resolutions": {
"styled-components": "^5"
}
}
JSON
복사
package.json
NOTE
Babel plugin도 사용하는 것이 좋다. 더 읽기 쉬운 클래스명, 서버사이드렌더링 호환성, 작은 번들 등과 같은 이점을 제공한다.
시작하기
styled-components는 템플릿 리터럴을 활용해 컴포넌트의 스타일을 지정하고, 컴포넌트와 스타일 간의 매핑을 제거한다.
// <h1>태그와 스타일을 렌더링할 Title 컴포넌트 만들기
const Title = styled.h1`
font-size: 1.5em;
text-align: center;
color: palevioletred;
`;
// <section> 태그와 스타일을 렌더링할 Wrapper 컴포넌트 만들기
const Wrapper = styled.section`
padding: 4em;
background: papayawhip;
`;
// Title과 Wrapper 컴포넌트를 사용
render(
<Wrapper>
<Title>
Hello World!
</Title>
</Wrapper>
);
Hello World!
JavaScript
복사
스타일이 첨부된 래퍼와 타이틀, 두 가지 컴포넌트 만드는 예제
NOTE
CSS규칙은 자동적으로 vendor prefix가 붙고, styled-components 가 이를 처리한다.
스타일드 컴포넌트는 CSS 규칙을 접두사로 지정하기 위해 내부적으로 stylis.js 패키지를 사용한다.
props 기반으로 적용하기
props를 기반으로 적용하기 위해, 스타일컴포넌트의 템플릿 리터럴에 함수를 전달할 수 있다.
const Button = styled.button`
/* 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;
`;
render(
<div>
<Button>Normal</Button>
<Button primary>Primary</Button>
</div>
);
NormalPrimary
JavaScript
복사
기본 prop을 true로 설정하면, 배경색과 텍스트 색이 바뀌는 버튼 예제
스타일 확장 (3개 중에 2번째거 쓰기)
컴포넌트를 꽤나 자주 사용하고 싶을 수 있지만, 단일 사례에 대해 가벼운 변경을 하라. 이제 보간된 함수를 전달하고 일부 props를 기반으로 변경할 수 있지만, 스타일을 한 번 재정의하는 데는 상당한 노력이 필요하다.
다른 컴포넌트의 스타일을 상속받는 새 컴포넌트를 쉽게 만들기 위해, styled() 생성자로 감싸면 된다.
Here we use the button from the last section and create a special one, extending it with some color-related styling:
// The Button from the last section without the interpolations
const Button = styled.button`
color: palevioletred;
font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border: 2px solid palevioletred;
border-radius: 3px;
`;
// A new component based on Button, but with some override styles
const TomatoButton = styled(Button)`
color: tomato;
border-color: tomato;
`;
render(
<div>
<Button>Normal Button</Button>
<TomatoButton>Tomato Button</TomatoButton>
</div>
);
Normal ButtonTomato Button
JavaScript
복사
We can see that the new TomatoButton still resembles Button, while we have only added two new rules.
In some cases you might want to change which tag or component a styled component renders. This is common when building a navigation bar for example, where there are a mix of anchor links and buttons but they should be styled identically.
For this situation, we have an escape hatch. You can use the "as" polymorphic prop to dynamically swap out the element that receives the styles you wrote:
const Button = styled.button`
display: inline-block;
color: palevioletred;
font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border: 2px solid palevioletred;
border-radius: 3px;
display: block;
`;
const TomatoButton = styled(Button)`
color: tomato;
border-color: tomato;
`;
render(
<div>
<Button>Normal Button</Button>
<Button as="a" href="#">Link with Button styles</Button>
<TomatoButton as="a" href="#">Link with Tomato Button styles</TomatoButton>
</div>
);
Normal ButtonLink with Button stylesLink with Tomato Button styles
JavaScript
복사
This works perfectly fine with custom components too!
const Button = styled.button`
display: inline-block;
color: palevioletred;
font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border: 2px solid palevioletred;
border-radius: 3px;
display: block;
`;
const ReversedButton = props => <Button {...props} children={props.children.split('').reverse()} />
render(
<div>
<Button>Normal Button</Button>
<Button as={ReversedButton}>Custom Button with Normal Button styles</Button>
</div>
);
Normal Buttonselyts nottuB lamroN htiw nottuB motsuC
JavaScript
복사
NOTE
If you are still on an older version than v4, you can use the .withComponent or .extend API's to achieve the same result as with the "as" prop, but note that this is discouraged as with v4 .extend was removed and .withComponent was marked as a candidate for future deprecation.
Styling any component (교안 참고)
The styled method works perfectly on all of your own or any third-party component, as long as they attach the passed className prop to a DOM element.
NOTE
If you are using react-native keep in mind to use style instead of className.
// This could be react-router-dom's Link for example
const Link = ({ className, children }) => (
<a className={className}>
{children}
</a>
);
const StyledLink = styled(Link)`
color: palevioletred;
font-weight: bold;
`;
render(
<div>
<Link>Unstyled, boring Link</Link>
<br />
<StyledLink>Styled, exciting Link</StyledLink>
</div>
);
Unstyled, boring Link
Styled, exciting Link
Plain Text
복사
NOTE
You can also pass tag names into the styled() factory call, like so: styled("div"). In fact, the styled.tagname helpers are just aliases that do the same.
Passed props
If the styled target is a simple element (e.g. styled.div), styled-components passes through any known HTML attribute to the DOM. If it is a custom React component (e.g. styled(MyComponent)), styled-components passes through all props.
This example shows how all props of the Input component are passed on to the DOM node that is mounted, as with React elements.
// Create an Input component that'll render an <input> tag with some styles
const Input = styled.input`
padding: 0.5em;
margin: 0.5em;
color: ${props => props.inputColor || "palevioletred"};
background: papayawhip;
border: none;
border-radius: 3px;
`;
// Render a styled text input with the standard input color, and one with a custom input color
render(
<div>
<Input defaultValue="@probablyup" type="text" />
<Input defaultValue="@geelen" type="text" inputColor="rebeccapurple" />
</div>
);
Plain Text
복사
Note how the inputColor prop is not passed to the DOM, but type and defaultValue are. That is styled-components being smart enough to filter non-standard attributes automatically for you.
Define Styled Components outside of the render method (외부에서 정의를 해라 정도 (교안 참고))
It is important to define your styled components outside of the render method, otherwise it will be recreated on every single render pass. Defining a styled component within the render method will thwart caching and drastically slow down rendering speed, and should be avoided.
Write your styled components the recommended way:
const StyledWrapper = styled.div`
/* ... */
`;
const Wrapper = ({ message }) => {
return <StyledWrapper>{message}</StyledWrapper>;
};
Plain Text
복사
Instead of:
const Wrapper = ({ message }) => {
// WARNING: THIS IS VERY VERY BAD AND SLOW, DO NOT DO THIS!!!
const StyledWrapper = styled.div`
/* ... */
`;
return <StyledWrapper>{message}</StyledWrapper>;
};
Plain Text
복사
Recommended reading: Talia Marcassa wrote a great review of real-world usage, featuring lots of solid practical insights and comparisons with alternatives, in Styled Components: To Use or Not to Use?
Pseudoelements, pseudoselectors, and nesting : 이 중에 하나 *가상요소, 가상요소선택자, 네스팅 (교안 참고)
Through this preprocessing, styled-components supports some advanced selector patterns:
•
& a single ampersand refers to all instances of the component; it is used for applying broad overrides:
const Thing = styled.div.attrs((/* props */) => ({ tabIndex: 0 }))`
color: blue;
&:hover {
color: red; // <Thing> when hovered
}
& ~ & {
background: tomato; // <Thing> as a sibling of <Thing>, but maybe not directly next to it
}
& + & {
background: lime; // <Thing> next to <Thing>
}
&.something {
background: orange; // <Thing> tagged with an additional CSS class ".something"
}
.something-else & {
border: 1px solid; // <Thing> inside another element labeled ".something-else"
}
`
render(
<React.Fragment>
<Thing>Hello world!</Thing>
<Thing>How ya doing?</Thing>
<Thing className="something">The sun is shining...</Thing>
<div>Pretty nice day today.</div>
<Thing>Don't you think?</Thing>
<div className="something-else">
<Thing>Splendid.</Thing>
</div>
</React.Fragment>
)
Hello world!
How ya doing?
The sun is shining...
Pretty nice day today.
Don't you think?
Splendid.
Plain Text
복사
•
&& a double ampersand refers to an instance of the component; this is useful if you're doing conditional styling overrides and don't want a style to apply to all instances of a particular component:
const Input = styled.input.attrs({ type: "checkbox" })``;
const Label = styled.label`
align-items: center;
display: flex;
gap: 8px;
margin-bottom: 8px;
`
const LabelText = styled.span`
${(props) => {
switch (props.$mode) {
case "dark":
return css`
background-color: black;
color: white;
${Input}:checked + && {
color: blue;
}
`;
default:
return css`
background-color: white;
color: black;
${Input}:checked + && {
color: red;
}
`;
}
}}
`;
render(
<React.Fragment>
<Label>
<Input defaultChecked />
<LabelText>Foo</LabelText>
</Label>
<Label>
<Input />
<LabelText $mode="dark">Foo</LabelText>
</Label>
<Label>
<Input defaultChecked />
<LabelText>Foo</LabelText>
</Label>
<Label>
<Input defaultChecked />
<LabelText $mode="dark">Foo</LabelText>
</Label>
</React.Fragment>
)
[x] Foo[ ] Foo[x] Foo[x] Foo
Plain Text
복사
•
&& a double ampersand alone has a special behavior called a "precedence boost"; this can be useful if you are dealing with a mixed styled-components and vanilla CSS environment where there might be conflicting styles:
const Thing = styled.div`
&& {
color: blue;
}
`
const GlobalStyle = createGlobalStyle`
div${Thing} {
color: red;
}
`
render(
<React.Fragment>
<GlobalStyle />
<Thing>
I'm blue, da ba dee da ba daa
</Thing>
</React.Fragment>
)
I'm blue, da ba dee da ba daa
Plain Text
복사
If you put selectors in without the ampersand, they will refer to children of the component.
const Thing = styled.div`
color: blue;
.something {
border: 1px solid; // an element labeled ".something" inside <Thing>
display: block;
}
`
render(
<Thing>
<label htmlFor="foo-button" className="something">Mystery button</label>
<button id="foo-button">What do I do?</button>
</Thing>
)
Mystery buttonWhat do I do?
Plain Text
복사
Attaching additional props v2
To avoid unnecessary wrappers that just pass on some props to the rendered component, or element, you can use the .attrs constructor. It allows you to attach additional props (or "attributes") to a component.
This way you can for example attach static props to an element, or pass a third-party prop like activeClassName to React Router's Link component. Furthermore you can also attach more dynamic props to a component. The .attrs object also takes functions, that receive the props that the component receives. The return value will be merged into the resulting props as well.
Here we render an Input component and attach some dynamic and static attributes to it:
const Input = styled.input.attrs(props => ({
// we can define static props
type: "text",
// or we can define dynamic ones
size: props.size || "1em",
}))`
color: palevioletred;
font-size: 1em;
border: 2px solid palevioletred;
border-radius: 3px;
/* here we use the dynamically computed prop */
margin: ${props => props.size};
padding: ${props => props.size};
`;
render(
<div>
<Input placeholder="A small text input" />
<br />
<Input placeholder="A bigger text input" size="2em" />
</div>
);
Plain Text
복사
As you can see, we get access to our newly created props in the interpolations, and the type attribute is passed down to the element.
11. Overriding .attrs (컴포넌트에 attr넣고 싶을때 )
Notice that when wrapping styled components, .attrs are applied from the innermost styled component to the outermost styled component.
This allows each wrapper to override nested uses of .attrs, similarly to how css properties defined later in a stylesheet override previous declarations.
Input's .attrs are applied first, and then PasswordInput's .attrs:
const Input = styled.input.attrs(props => ({
type: "text",
size: props.size || "1em",
}))`
border: 2px solid palevioletred;
margin: ${props => props.size};
padding: ${props => props.size};
`;
// Input's attrs will be applied first, and then this attrs obj
const PasswordInput = styled(Input).attrs({
type: "password",
})`
// similarly, border will override Input's border
border: 2px solid aqua;
`;
render(
<div>
<Input placeholder="A bigger text input" size="2em" />
<br />
{/* Notice we can still use the size attr from Input */}
<PasswordInput placeholder="A bigger password input" size="2em" />
</div>
);
Plain Text
복사
This is why PasswordInput is of a password type, but still uses the size attribute from Input.
12. Animations
CSS animations with @keyframes aren't scoped to a single component but you still don't want them to be global to avoid name collisions. This is why we export a keyframes helper which will generate a unique instance that you can use throughout your app:
// Create the keyframes
const rotate = keyframes`
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
`;
// Here we create a component that will rotate everything we pass in over two seconds
const Rotate = styled.div`
display: inline-block;
animation: ${rotate} 2s linear infinite;
padding: 2rem 1rem;
font-size: 1.2rem;
`;
render(
<Rotate>< 💅🏾 ></Rotate>
);
< 💅🏾 >
Plain Text
복사
NOTE
Keyframes are lazily injected when they're used, which is how they can be code-split, so you have to use the css helper for shared style fragments:
const rotate = keyframes``
// ❌ This will throw an error!
const styles = `
animation: ${rotate} 2s linear infinite;
`
// ✅ This will work as intended
const styles = css`
animation: ${rotate} 2s linear infinite;
`
Plain Text
복사
NOTE
This used to work in v3 and below where we didn't code-split keyframes. If you're upgrading from v3, make sure that all your shared style fragments are using the css helper!
Advanced Usage
Theming(공부 후 추가)
styled-components has full theming support by exporting a <ThemeProvider> wrapper component. This component provides a theme to all React components underneath itself via the context API. In the render tree all styled-components will have access to the provided theme, even when they are multiple levels deep.
To illustrate this, let's create our Button component, but this time we'll pass some variables down as a theme.
// Define our button, but with the use of props.theme this time
const Button = styled.button`
font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border-radius: 3px;
/* Color the border and text with theme.main */
color: ${props => props.theme.main};
border: 2px solid ${props => props.theme.main};
`;
// We are passing a default theme for Buttons that arent wrapped in the ThemeProvider
Button.defaultProps = {
theme: {
main: "palevioletred"
}
}
// Define what props.theme will look like
const theme = {
main: "mediumseagreen"
};
render(
<div>
<Button>Normal</Button>
<ThemeProvider theme={theme}>
<Button>Themed</Button>
</ThemeProvider>
</div>
);
JavaScript
복사
Function themes
You can also pass a function for the theme prop. This function will receive the parent theme, that is from another <ThemeProvider> higher up the tree. This way themes themselves can be made contextual.
This example renders our above themed Button and a second one that uses a second ThemeProvider to invert the background and foreground colors. The function invertTheme receives the upper theme and creates a new one.
// Define our button, but with the use of props.theme this time
const Button = styled.button`
color: ${props => props.theme.fg};
border: 2px solid ${props => props.theme.fg};
background: ${props => props.theme.bg};
font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border-radius: 3px;
`;
// Define our `fg` and `bg` on the theme
const theme = {
fg: "palevioletred",
bg: "white"
};
// This theme swaps `fg` and `bg`
const invertTheme = ({ fg, bg }) => ({
fg: bg,
bg: fg
});
render(
<ThemeProvider theme={theme}>
<div>
<Button>Default Theme</Button>
<ThemeProvider theme={invertTheme}>
<Button>Inverted Theme</Button>
</ThemeProvider>
</div>
</ThemeProvider>
);
JavaScript
복사
Getting the theme without styled components
via withTheme higher-order component
If you ever need to use the current theme outside styled components (e.g. inside big components), you can use the withTheme higher order component.
import { withTheme } from 'styled-components'
class MyComponent extends React.Component {
render() {
console.log('Current theme: ', this.props.theme)
// ...
}
}
export default withTheme(MyComponent)
JavaScript
복사
Refs v4(공부 후 추가)
Passing a ref prop to a styled component will give you one of two things depending on the styled target:
•
the underlying DOM node (if targeting a basic element, e.g. styled.div)
•
a React component instance (if targeting a custom component e.g. extended from React.Component)
const Input = styled.input`
padding: 0.5em;
margin: 0.5em;
color: palevioletred;
background: papayawhip;
border: none;
border-radius: 3px;
`;
class Form extends React.Component {
constructor(props) {
super(props);
this.inputRef = React.createRef();
}
render() {
return (
<Input
ref={this.inputRef}
placeholder="Hover to focus!"
onMouseEnter={() => {
this.inputRef.current.focus()
}}
/>
);
}
}
render(
<Form />
);
Plain Text
복사
NOTE
Using an older version of styled-components (below 4.0.0) or of React? Use the innerRef prop instead.
Security(공부 후 추가)
Since styled-components allows you to use arbitrary input as interpolations, you must be careful to sanitize that input. Using user input as styles can lead to any CSS being evaluated in the user's browser that an attacker can place in your application.
This example shows how bad user input can even lead to API endpoints being called on a user's behalf.
// Oh no! The user has given us a bad URL!
const userInput = '/api/withdraw-funds'
const ArbitraryComponent = styled.div`
background: url(${userInput});
/* More styles here... */
`
Plain Text
복사
Be very careful! This is obviously a made-up example, but CSS injection can be unobvious and have bad repercussions. Some IE versions even execute arbitrary JavaScript within url declarations.
There is an upcoming standard to sanitize CSS from JavaScript, CSS.escape. It's not very well supported across browsers yet, so we recommend using the polyfill by Mathias Bynens in your app.