ReactJS_스터디 15일차 (23/02/20)

yhwa·2023년 2월 19일
0
post-thumbnail

📝 React JS 마스터클래스: From #2.0 to #2.7

Styled Components 와 ReactJS
Styled Components의 설정값을 변경하여 확장하여 사용하기

⛳️ Styled Components 와 ReactJS

🔗 Styled Component Doc [LINK]

- 다크 모드, 라이트 모드 구현을 쉽게 도와줍니다.
- 

Styled-Components 이전의 ReactJS 스타일 관리

- global.css (전역적으로 모든 페이지에 기본적으로 적용되는 CSS)
- 인라인 스타일 (html마크업의 style속성으로 직접 코딩하는 CSS)
- fileName-module.css (CSS모듈로 만들어서 해당 페이지에만 적용)
- 모듈형태는 className을 마치 오브젝트의 속성처럼 사용합니다.
- ex) <div className={styles.title}></div>

👉 모듈형태로 사용하는것이 가장 편리합니다.
- CSS 모듈 방식은 className을 랜덤하게 만들어줘서, className이 서로 충돌하지 않습니다.

...ReactJS에서 style을 작업하는 최선의 방법은 Styled-Components 입니다.

Styled-Components Install

- 콘솔창에서 styled-components를 설치하고 
- package.json에서 dependencies에 추가되었는지 확인합니다.
npm i styled-components

인라인 스타일 방식과 비교하기

- html 마크업의 style속성에 작성합니다, 
- 작성 후, 바로 이해하기 쉽고 별도 CSS파일 생성이 필요하지 않습니다.

👉 괄호를 열고 JS코드방식으로 작성해야하며, 때문에 직관적이지 않습니다.
같은 태그를 사용하면, CSS를 살펴보지 않고는 각각의 컴포넌트의 역할을 파악할 수 없습니다.
function App() {
	return (
    	<div style={{ display: "flex" }}>
      		<div style={{ backgroundColor: "teal", width: 100, height: 100 }}></div>
      		<div style={{ backgroundColor: "tomato", width: 100, height: 100 }}></div>
    	</div>
    );
}

export default App;

Styled-Components 방식

- 모든 스타일은 컴포넌트를 사용하기 전에 미리 컴포넌트에 포함시킬 수 있습니다.
- CSS 코드를 CSS 방식 그대로 사용할 수 있고, 
- 작성된 컴포넌트를 보면 직관적으로 구별할 수 있습니다.
- 클래스이름이 자동으로 랜덤 텍스트로 부여됩니다.
- 클래스이름을 개발자가 만들 필요가 없습니다.
- html마크업 속성으로 style을 작성할 필요가 없습니다.
- 유효한 html태그 이름을 사용해야하며, 백틱(``) 사이에는 CSS 코드가 작성됩니다.
- 컴포넌트 끼리 공통요소가 많고, 다른부분이 적다면 중복되는 코드를 줄일 수 있습니다.
- 컴포넌트의 전체적인 영역을 style과 구현부로 나눌 수 있습니다.
- styled-components를 활용하며, 구현부 가독성이 높아졌습니다.
import styled from "styled-components";

const Fater = styled.div`
	display:flex;
`;

const BoxOne = styled.div`
  background-color: tomato;
  width: 100px;
  height: 100px;
`;

const BoxTwo = styled.div`
  background-color: teal;
  width: 100px;
  height: 100px;
`;

const Text = styled.span`
  font-weight: bold;
  color:#ffffff;
  font-size:30px;
`;

Function App(){
	return (
    	<Father>
      		<BoxOne>
      			<Text>Box1</Text>
      		</BoxOne>
      		<BoxTwo>
      			<Text>Box2</Text>
      		</BoxTwo>
      	</Father>
    );
}

export default App;

Styled-Components 확장하여 사용하기 01

- 특정 값을 제외하고 다른 스타일이 모두 같아 중복되는 컴포넌트 작업하기
- BoxOne과 BoxTwo는 텍스트의 컬러값만 제외하고 모두 스타일이 같습니다.
- 컴포넌트에서 color값을 결정하는 것이 아닌, Props를 사용하여 Box의 설정값에서 설정합니다.
- props란 컴포넌트에 데이터를 보내는 방식을 말합니다.
- props의 이름을 작성합니다. props의 네이밍은 어느것이든 가능합니다.
- 이름을 정한 props에 값을 부여하면 prop를 보내는 작업이 완료됩니다.
- props라는 파라미터를 받는 함수를 스타일에서 적어줍니다.
- 커스텀 props를 스타일에 사용하면 styled-components가 자동으로
- className을 작성하고 style을 분류합니다.
- props를 이용하여 컴포넌트 설정이 가능합니다.
- props는 컴포넌트에 데이터를 보내는 방법입니다.
- 또한 이것이 styled-components에서 props를 받고 사용하는 방법입니다.
- props를 통해 컴포넌트를 설정하는 방법
import styled from "styled-components";

const Fater = styled.div`
	display:flex;
`;

const Box = styled.div`
  background-color: ${props => props.bgColor};
  width: 100px;
  height: 100px;
`;

Function App(){
	return (
    	<Father>
      		<Box bgColor="tomato"/>
      		<Box bgColor="teal"/>
      	</Father>
    );
}

export default App;

Styled-Components 확장하여 사용하기 02

- 기존 컴포넌트의 모든 것들을 가져와 새로운 것들을 더하는 방식입니다.
- 중복되는 코드를 축소합니다.
- 컴포넌트를 확장하여 사용해야하는 이유는 중복되는 코드를 최소화하기 위함입니다.
- 특정 컴포넌트를 기존 컴포넌트에 더하는 방식입니다.
- Box의 모든 속성들을 들고 온 다음, 추가로 더할 코드에 합칩니다.
- "const circle = styled(Box)" 형식으로 기존 컴포넌트를(Box) 가져와서 더합니다.
- 괄호 안에 더하고 싶은 기존 컴포넌트를 넣어 확장시킵니다.
import styled from "styled-components";

const Fater = styled.div`
	display:flex;
`;

const Box = styled.div`
  background-color: ${props => props.bgColor};
  width: 100px;
  height: 100px;
`;

const circle = styled(Box)`
	border-radius:50%;
`;

Function App(){
	return (
    	<Father>
      		<Box bgColor="tomato"/>
      		<Circle bgColor="green"/>
      	</Father>
    );
}

export default App;

Styled-Components Tricks > AS

- 컴포넌트의 태그는 바꾸고싶은데, 스타일은 변경하고 싶지 않은 경우 작업하기
- "const Link = styled(Btn)" 방식은 같은 컴포넌트를 사용하는 것이 아니라,
- 기존 스타일을 확장하는 방법입니다.
- <Btn as="a">Link</Btn> "as" props를 사용하여 스타일은 그대로 유지하고, 
- 태그의 종류만 변경하여 재사용합니다.
- "as" props를 사용해서 태그의 종류를 button에서 a로 바꾸면
- 그 태그의 속성도 사용할 수 있습니다. (href="" 사용가능)
- 스타일을 추가할 계획이 없고 컴포넌트를 확장시키고 싶지 않을때, 
- 태그의 종료만 변경할때, 사용합니다.
import styled from "styled-components";

const Fater = styled.div`
	display:flex;
`;

const Btn = styled.button`
  color: #ffffff;
  background-color: pink;
  border:0;
  border-radius: 15px;
`;

Function App(){
	return (
    	<Father>
      		<Btn>Login</Btn>
      		<Btn as="a" href="/">Link</Btn>
      	</Father>
    );
}

export default App;

Styled-Components Tricks > Attr

- html의 속성값을 설정할 수 있게 해줍니다.
- const Input = styled.input.attrs({ required:true })
- attrs로 html태그의 속성의 프로퍼티를 설정할 수 있습니다.
- const Input = styled.input.attrs({required:true, maxLength=4})
- 객체 안에 복수를 설정할 수 있습니다.
- 스타일뿐만 아니라 html속성 설정까지 컴포넌트로 작업하여 재사용이 가능합니다.
import styled from "styled-components";

const Fater = styled.div`
	display:flex;
`;

const Input = styled.input.attrs({ required:true, maxLength=4 })`
  border:0;
  background-color:lightgray;
`;

Function App(){
	return (
    	<Father>
      		<Input />
      	</Father>
    );
}

export default App;

Styled-Components Tricks > Animation

- helper function(keyframes)를 import합니다.
- animation에 대한 정의를하고 사용할 컴포넌트에 animation으로 변수 호출을 합니다.
- keyframes+백틱 내부에는 일반 css애니메이션 속성을 작성합니다.
- animation 정의 영역에 변수를 작성할때, 
- JS의 string interpolation을 사용합니다. ${variable}
import styled, {keyframes} from "styled-components";

const rotateAnimation = keyframes`
	0% {
		transform:rotate(0deg);
		border-radius:0%;
	}
	
	50% {
		transfrom:rotate(360deg);
		border-radius:50%
	}

	100% {
		transform:rotate(0deg);
		border-radius:0%;
	}
`;

const Wrapper = styled.div`
	display:flex;
`;

const Box = styled.div`
	width:100px;
	height:100px;
	background-color:tomato;
	animation:${rotateAnimation} 10s linear infinite;
`;

Function App(){
	return (
    	<Wrapper>
      		<Box>
      			<span></span>
      		</Box>
      	</Wrapper>
    );
}

export default App;

Styled-Components Tricks > Selector

- 컴포넌트에서 selector를 하나 더 사용하는 방법이 있습니다.
- 컴포넌트 내부에 있는 styled-components가 아닌 요소를 타겟하는 방법
- Box style내부에 span에 대한 CSS를 작성합니다.
- 컴포넌트의 하위요소중 styled-component가 아닌것은 style내부에서
- 타겟하여 스타일을 작성할 수 있습니다.
- 모든 요소를 styled-component화 할 필요는 없지만, 대신 컴포넌트만
- styled-components 스타일처리를 하고, 다른것은 target처리 가능합니다.
import styled, {keyframes} from "styled-components";

const rotateAnimation = keyframes`
	0% {
		transform:rotate(0deg);
		border-radius:0%;
	}
	
	50% {
		transfrom:rotate(360deg);
		border-radius:50%
	}

	100% {
		transform:rotate(0deg);
		border-radius:0%;
	}
`;

const Wrapper = styled.div`
	display:flex;
`;

const Box = styled.div`
	width:100px;
	height:100px;
	background-color:tomato;
	animation:${rotateAnimation} 10s linear infinite;

	span {
		font-size:60px;
	}
`;

Function App(){
	return (
    	<Wrapper>
      		<Box>
      			<span>🤔</span>
      		</Box>
      	</Wrapper>
    );
}

export default App;

Styled-Components Tricks > Pseudo Selector 01 & hover

- styled-component "안에" 있는 것을 select하도록 도와줍니다.
- 함축된(encapsulated) 표현으로 빠르게 작업할 수 있습니다.
- ^ 나 & 처리를 해줄 수 있습니다. ex) &:hover (=pseudo selector)
- span 내부에 &hover: 와 span:hover 는 같은 기능을 합니다.
- &란 span을 호명하는 것과 같습니다. 단축키와 같아서, 더 빨리 사용할 수 있습니다.
- 마우스를 클릭하고 있는 상태가 active, 아닌상태가 inactive입니다.
- 이 방법은 tag name에 의존하고 있으므로 변경되면 적용되지 않습니다.
- tag name에 의존하고싶지 않다면, styled-component를 적용해야합니다.
const Box = styled.div`
	width:100px;
	height:100px;
	background-color:tomato;
	animation:${rotateAnimation} 10s linear infinite;

	span {
		font-size:60px;

		&:hover {
			font-size:20px;
		}

		&:active {
			opacity:0;
		}
	}

	/* span:hover {
		font-size:20px;
	} 
	span:active {
		opacity:0;
	}*/
`;

Styled-Components Tricks > Pseudo Selector 02

- styled-components안의 element를 선택하는 다른 방법입니다.
- 컴포넌트 안에 또 컴포넌트를 적용할 수 있습니다.
- tag name에 의존하지 않고 컴포넌트 하위 엘리먼트를 타겟팅하기위해서는, 
- ${Emoji}처럼 string interpolation안에 변수를 넣습니다.
- 하위 요소를 컴포넌트 변수화하여 넣으면, tag name이 변해도 그대로 스타일이 유지됩니다.
const Emoji = styled.span`
	font-size:100px;
`;

const Box = styled.div`
	width:100px;
	height:100px;
	background-color:tomato;
	animation:${rotateAnimation} 10s linear infinite;

	${Emoji}{
		&:hover {
			font-size:20px;
		}
	}

	/* ${Emoji}:hover {
		font-size:20px;
	} */
`;

Function App(){
	return (
    	<Wrapper>
      		<Box>
      			<Emoji>🤔</Emoji>
      		</Box>
      	</Wrapper>
    );
}

export default App;

Styled-Components > Theme으로 dark/light mode 구현

- themes는 앱이 light/dark 모드를 가지게 해줍니다.
- styled-component의 Theme & Local Estate Management를 
- 합쳐서 다크모드를 구현합니다.
- theme이란, 기본적으로 모든 색상들을 가지고 있는 object입니다.
- 색상을 하나의 객체에 모두 넣어놨기때문에 매우 유용합니다.
- ThemeProvider라는 것을 styled-components로부터 import합니다.
- ThemeProvider는 theme이라는 props가 필요합니다.
- darkmode와 lightmode에 대한 스타일 객체를 정의합니다.
- App.js가 ThemeProvider내부에 있기때문에 필요하면 
- App.js안에서 해당 객체에 접근할 수 있습니다.
- ThemeProvider에서 가져온 색들 중 구체적인 색상을 정하고, 
- ThemeProvider에 둘러싸인 모든 컴포넌트는 theme의 데이터에 접근할 수 있습니다.
- theme을 2가지 이상 만들고, 서로 같은 프로퍼티 이름을 가져야합니다.
- darkmode에서 lighttheme으로 변경해줄때 같은 프로퍼티가 필요합니다.
- 오직 theme에 대한 레퍼런스만 가질 뿐, 색상에 대한 언급은 작성하지 않습니다.
- theme의 색상은 변경되었지만 다른 컴포넌트에는 변화가 없습니다.
- 하나만 변경해도 전부 자동으로 변경됩니다.
- 프로퍼티를 몇가지 가진 theme객체만 정의되면 됩니다.
- 그 객체를 ThemeProvider에게 전달합니다. 
- 그러면 ThemeProvider내부에 있는 모든 컴포넌트에서 theme오브젝트에 접근할 수 있게됩니다.
- 2개의 theme객체를 만들고, 서로 동일한 프로퍼티 이름을 갖고있으면 됩니다.
- light/dark mode를 작업하려면 서로 프로퍼티의 이름을 가져야합니다.
- 코드 하나만 바꿔주면 앱 전체에 변화가 생깁니다.
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import { ThemeProvider } from "styled-components";

const darkTheme = {
  textColor: "whitesmoke",
  bgColor: "#000000"
}

const lightTheme = {
  textColor: "#000000",
  bgColor: "whitesmoke"
}

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <ThemeProvider theme={darkTheme}>
      <App />
    </ThemeProvider>
  </React.StrictMode>
);
mport styled from "styled-components";

const Wrapper = styled.div`
  display: flex;
  width:100vw;
  height: 100vh;
  justify-content: center;
  align-items: center;
  background-color: ${props => props.theme.bgColor};
`;

const Text = styled.div`
  color:${props => props.theme.textColor};
  font-size:100px;
  font-weight:bold;
`;


function App() {
  return (
    <Wrapper>
      <Text>Hello :)</Text>
    </Wrapper>
  );
}

export default App;
profile
📌 FE 공부 정리 공간입니다.

0개의 댓글