:부품 단위로 UI 컴포넌트를 만들어 나가는 개발
(기획 단계에서부터 디자이너, 기획자와 이 컴포넌트 부품들을 함께 공유힐 수 있음)
React 환경에서 사용가능한 CSS를 컴포넌트화 시킬 수 있는 라이브러리.
//터미널에 명령어 입력
//with npm
$ npm install --save styled-components
//with yarn
$ yarn add styled-components
//사용할 파일로 불러와주기
import styled from "styled-components"
//package.json에 다음 코드 추가
//여러 버전의 Styled Components가 설치되어 발생하는 문제를 줄여줍니다.
{
"resolutions": {
"styled-components": "^5"
}
}
//사용 예시
import styled from "styled-components";
const BlueButton = styled.button`
background-color : blue;
color: white;
`;
export default function App() {
// React 컴포넌트를 사용하듯이 사용.
return <BlueButton>Blue Button</BlueButton>;
}
//위에서 만든 BlueButton 재활용
const BigBlueButton = styled(BlueButton)`
padding:10px;
margin-top:10px;
`;
//1.props로 조건부 렌더링
//Button 컴포넌트에 skyblue라는 props가 있는지 확인하고
//있으면 배경색으로 skyblue, 없으면 white 지정
const Button = styled.button`
background: ${(props)=> props.skyblue? "skyblue":"white"}
`;
//2.props 값으로 렌더링하기
//props.color가 없다면 white, 있으면 porps.color 값 그대로 가져와 스타일 속성으로 리턴
const Button = styled.button`
background : ${(props)=> props.color? props.color:"white"}
`;
//삼항 연산자만 사용해야하는 건 아님
//js 코드라면 뭔든 가능
const Button = styled.button`
background:${(props)=>props.color||"white"}
//아래 예시에서 return 문 속의 Button 요소에 skyblue라는 props가 전달되었음
import styled from "styled-components";
const Button1 = styled.button`
background: ${(props) => (props.skyblue ? "skyblue" : "white")};
`;
export default function App() {
return (
<>
<Button skyblue>Button1</Button>
</>
);
}
//createGlobalStyle 가져오기
import {createGlobalStyle} from "styled-components";
//위 함수 사용해 설정해주고 싶은 스타일 작성
const GlobalStyle = createGlobalStyle`
button {
padding : 5px;
margin : 2px;
border-radius : 5px;
}
`;
//만들어진 GlobalStyle 컴포넌트를 최상위 컴포넌트에 사용해줌
function App(){
return (
<>
<GlobalStyle />
<Button>전역 스타일 적용하기</Button>
</>
);
}
Component Explorer(컴포넌트 탐색기)에 많은 UI 개발 도구가 다양하게 있는데, 그중 하나가 Storybook
각각의 컴포넌트들을 따로 볼 수 있게 구성해주어 한 번에 하나의 컴포넌트에서 작업할 수 있음.
재사용성 확대 위해 컴포넌트를 문서화하고, 자동으로 컴포넌트를 시각화해 시뮬레이션 할 수 있는 다양한 테스트 가능. 버그 사전 방지도 가능.
테스트 및 개발 속도 향상시키는 장점. 애플리케이션 또한 의존성 걱정 않고 빌드 가능.
주요 기능 : UI 컴포넌트들 카탈로그화 / 컴포넌트 변화를 Stories로 저장 / 핫 모듈 재로딩과 같은 개발 툴 경험 제공 / 리액트 포함한 다양한 뷰 레이어 지원
npx create-react-app storybook-practice
npx storybook init //만들어진 리액트 프로젝트 폴더를 vscode로 열어서 해당 파일 터미널에서 설치
npm run storybook//실행
만들 버튼 엘리먼트나 타이틀 엘리먼트를 위한 js 페이지를 만들고, 내용을 작성.
같은 이름에 뒤에 .stories.js를 붙인 파일을 만들면 알아서 스토리로 인식함. 스토리도 작성.
//Button.js
import React from "react";
import styled from "styled-components";
const StyledButton = styled.button`
background: ${(props) => props.color || "white"};
width: ${(props) => (props.size === "big" ? "200px" : "100px")};
height: ${(props) => (props.size === "big" ? "80px" : "40px")};
`;
const Button = ({ color, size, text }) => (
<StyledButton color={color} size={size}>
{text}
</StyledButton>
);
export default Button;
//Button.stories.js
import Button from "./Button";
// title : 컴포넌트 이름으로, '/'를 넣어 카테고리화 할 수 있음. (아래 이미지에 Practice라는 카테고리 생성된 것 볼 수 있음)
// component : 어떤 컴포넌트를 가져와서 스토리로 만들 것인지 명시합니다.(Import 해온 Button)
// argTypes : 컴포넌트에 필요한 전달인자의 종류와 타입을 정해줍니다.
// 지금은 text 라는 전달인자에 text 타입이 필요함을 의미합니다. (나머지들도 다 종류들임)
export default {
title: "Practice/Button",
component: Button,
argTypes: {
color: { control: "color" },
size: { control: { type: "radio", options: ["big", "small"] } },
text: { control: "text" },
},
};
export const StorybookButton = (args) => <Button {...args}></Button>;
빨간 상자 속 부분이 실습으로 만들어진 탬플릿(?)
모든 개발 요구 사항을 React로 충족하기는 힘듦.
DOM 엘리먼트 주소값을 활용해야 하는 경우가 있음.
💡 DOM 엘리먼트 주소값 활용해야 하는 경우
- focus
- text selection
- media playback
- 애니메이션 적용
- d3.js, greensock 등 DOM 기반 라이브러리 활용
React는 이런 예외적 상황에서 useRef로 DOM 노드, 엘리먼트, React 컴포넌트 주소값을 참조할 수 있음.
useRef를 통해 DOM을 직접 조작시 리렌더링이 되지 않음.
그리고 useRef를 통해 값을 저장시 리렌더링 후 값이 초기화가 되지 않음.
따라서 렌더링 여부에 상관없이 값을 유지하고 싶을때 사용되기도 함.
특정 DOM 요소에서 써야하는 매서드를 사용해야 할 때 쓴다
매서드 안 써도 React 상에서 할 수 있는 거면 state나 props 사용
const 주소값을_담는_그릇 = useRef(참조자료형)
return (
<div>
<input ref={주소값을_담는_그릇} type="text" />
</div>);
// React에서 사용 가능한 ref라는 속성에 주소값을_담는_그릇을 값으로 할당하면
//주소값을_담는_그릇 변수에는 input DOM 엘리먼트의 주소가 담김.
//이 주소값은 컴포넌트가 re-render 되더라도 바뀌지 않음
//향후 다른 컴포넌트에서 input DOM 엘리먼트를 활용 가능.
function TextInputWithFocusButton(){
const inputEl = useRef(null);
//inputEl이라는 주소값을 담는 그릇이 생김
const onButtonClick = () => {
inputEl.current.focus();
};
//onButtonClick이라는 함수는 실행되면 inputEl이라는 주소값에 해당하는 DOM요소(current)에
//focus()라는 매서드를 실행하는 함수이다.
return (
<>
<input ref={inputEl} type="text" />
<button onClick={onButtonClick}>Focus the input</button>
</>);
}
//ref라는 속성에 inputEl이라는 주소값 담는 그릇을 값으로 할당해놓아서
//input의 주소가 담겨서 사용할 수 있었던 것.