CSS-in-JS
styled-components 설치
: 리액트에서 CSS-in-JS 방식으로 component를 꾸밀 수 있게 도와주는 패키지
# git bash에서 yarn 명령어로 설치
yarn add styled-components
styled-components plugin 설치
: VScode에서 style 코드를 편하게 작성하기 위해 제공해 주는 플러그인
vscode의 Extensions -> vscode-styled-component 검색 후 라이브러리 install
styled-component 사용 예시)
// src/App.js
import React from "react";
import styled from "styled-components";
// 1. styled-components
const StBox = styled.div`
width: 100px;
height: 100px;
border: 1px solid ${(props) => props.borderColor};
// 4.부모 컴포넌트에서 보낸 props를 받아 사용
margin: 20px;
`;
const App = () => {
return (
<div>
{/* 2. 위에서 만든 styled-components를 사용 */}
{/* 3. props를 통해 borderColor라는 값을 전달 */}
<StBox borderColor="red">빨간 박스</StBox>
<StBox borderColor="green">초록 박스</StBox>
<StBox borderColor="blue">파랑 박스</StBox>
</div>
);
};
export default App;
styled-component 장점
: style을 작성할 때 if문, switch문, 삼항연산자 등을 구현하기 위해 쓰여 className에 비해 조건부 스타일링을 하기 쉬움
ex) 같은 StBox여도 borderColor를 다르게 설정할 수 있음 (props를 통해 전달해 줌으로써 조건부스타일링 구현)
map을 이용해 리팩토링!
// src/App.js
import React from "react";
import styled from "styled-components";
// styled-components
const StBox = styled.div`
width: 100px;
height: 100px;
border: 1px solid ${(props) => props.borderColor};
// 부모 컴포넌트에서 보낸 props를 받아 사용
margin: 20px;
`;
const boxList = ["red", "green", "blue"];
// 색을 넣으면 이름을 반환해주는 함수 만들기
const getBoxName = (color) => {
switch (color) {
case "red":
return "빨간 박스";
case "green":
return "초록 박스";
case "blue":
return "파란 박스";
default:
return "검정 박스";
}
};
const App = () => {
return (
<div>
{boxList.map((box) => (
<StBox borderColor={box}>{getBoxNam(box)}</StBox>
))}
{/* 각각의 컬러(box)에 대해 */}
{/* borderColor는 color값 {box}을 주고, 그 컬러에 따른 {boxName(box)}을 호출하는 함수 */}
</div>
);
};
export default App;
React Hook
useState: 가장 기본적인 hook이면서 함수 컴포넌트에서 가변적인 상태를 가지게 해 준다. 즉, 상태관리를 할 수 있게 해 줌. 중요하고 자주 쓰이는 hook
//useState의 기본적인 형태
const [state, setState] = useState(initialState);
useState 함수가 배열을 반환하고, 이것을 구조 분해 문법으로 꺼내놓은 모습!
state를 변수로 사용하고 setState를 이용해서 state 값을 수정할 수 있음
만약 state가 원시 데이터타입이 아닌 객체 데이터 타입인 경우에는 불변성을 유지해줘야 한다
함수형 업데이트
// 기존에 사용하던 방식
setState(number + 1);
// 함수형 업데이트
setState(() => {});
setState의 ( ) 안에 수정할 값이 아니라 함수를 넣을 수 있음
그리고 그 함수의 인자에서는 현재의 state을 가져올 수 있고, { } 안에서는 이 값을 변경하는 코드를 작성할 수 있음
// 현재 number의 값을 가져와서 그 값에 +1을 더하여 반환
setState((currentNumber)=>{ return currentNumber + 1 });
일반 업데이트 방식 & 함수형 업데이트 방식 차이
일반 업데이트 방식: onClick안에서 setNumber(number + 1) 를 3번 호출했는데 number가 1씩 증가
이유: 버튼을 클릭했을 때 첫번째 줄 ~ 세번째 줄의 있는 setNumber가 각각 실행되는 것이 아니라, 배치(batch)로 처리한다. 즉 onClick을 했을 때 setNumber 라는 명령을 세번 내리지만, 리액트는 그 명령을 하나로 모아 최종적으로 한번만 실행
// 일반 업데이트 방식
// src/App.js
import { useState } from "react";
const App = () => {
const [number, setNumber] = useState(0);
return (
<div>
{/* 버튼을 누르면 1씩 플러스된다. */}
<div>{number}</div>
<button
onClick={() => {
setNumber(number + 1); // 첫번째 줄
setNumber(number + 1); // 두번쨰 줄
setNumber(number + 1); // 세번째 줄
}}
>
버튼
</button>
</div>
);
}
export default App;
함수형 업데이트 방식: number가 3씩 증가
이유: 3번을 동시에 명령을 내리면 그 명령을 모아 순차적으로 각각 1번씩 실행
// 함수형 업데이트 방식
// src/App.js
import { useState } from "react";
const App = () => {
const [number, setNumber] = useState(0);
return (
<div>
{/* 버튼을 누르면 3씩 플러스 된다. */}
<div>{number}</div>
<button
onClick={() => {
setNumber((previousState) => previousState + 1);
setNumber((previousState) => previousState + 1);
setNumber((previousState) => previousState + 1);
}}
>
버튼
</button>
</div>
);
}
export default App;
useEffect
: react component가 렌더링이 될 때마다 특정 작업을 수행할 수 있게 하는 hook
(component가 화면에 보이거나 사라졌을 때 무언가를 실행하려면 useEffect 사용)
import React, { useEffect } from "react";
import를 해야 사용할 수 있음!
import React, { useEffect } from "react";
const App = () => {
useEffect(() => {
// 이 부분이 실행
console.log("hello useEffect");
});
return <div>Home</div>;
};
App component가 화면에 렌더링 될 때 실행
// 크롬 콘솔창에 출력
hello useEffect
hello useEffect
hello useEffect 가 두 번 출력되는 이유
: useEffect가 2번 실행된 것이 아니라 strictmode가 적용되어 있기 때문!
리렌더링(re-rendering)과 리렌더링 문제 해결
리렌더링 예시↓
import React, { useEffect, useState } from "react";
const App = () => {
const [value, setValue] = useState("");
useEffect(() => {
console.log("hello useEffect");
});
return (
<div>
<input
type="text"
value={value}
onChange={(event) => {
setValue(event.target.value);
}}
/>
</div>
);
}
export default App;
state가 변경되면 리렌더링이 일어남 -> input값을 입력하면 App component가 리렌더링되는데, 리렌더링이 되었기 때문에 useEffect가 또 다시 한 번 진행됨
그래서 브라우저에서 input에 어떤 값을 입력할 때마다 useEffect가 계속 실행되는 것!!!
동영상 서비스가 종료되어 해당 콘텐츠를 재생할 수 없습니다.
리렌더링 문제 해결법
: 의존성배열(useEffect를 제어-함수의 실행조건을 제어-할 수 있는 방법)
이 배열에 값을 넣고, 그 값이 바뀔 때만 useEffect를 실행
// useEffect의 두번째 인자가 의존성 배열이 들어가는 곳
useEffect(()=>{
// 실행하고 싶은 함수
}, [의존성배열])
비어있는 의존성배열
: 처음 한 번만 실행이 되고, 그 이후로는 어떤 일도 일어나서는 안 됨
어떤 값이 변할 때마다 바뀌는데(useEffect 실행) 주어진 값이 없기 때문
import React, { useEffect, useState } from "react";
const App = () => {
const [value, setValue] = useState("");
useEffect(() => {
console.log("hello useEffect");
}, []); // 비어있는 의존성배열
// '이 배열 안에 값을 넣으면, 그 값이 바뀔 때만 useEffect를 실행하라'는 의미
return (
<div>
<input
type="text"
value={value}
onChange={(event) => {
setValue(event.target.value);
}}
/>
</div>
);
};
export default App;
input에 어떤 값을 입력하더라도 처음에 실행된 hello useEffect 외에는 더 이상 실행이 되지 않음
동영상 서비스가 종료되어 해당 콘텐츠를 재생할 수 없습니다.
∴ 어떤 함수를 컴포넌트가 렌더링 될 때 단 한번만 실행하고 싶으면 의존성 배열을 [ ] 빈 상태로 넣으면 된다
의존성배열에 값이 있는 경우
: 최초 렌더링 뿐만 아니라 해당 값이 변할 때마다 useEffect 안에 있는 코드(console.log("hello useEffect");)도 계속 실행이 됨
// src/App.js
import React, { useEffect, useState } from "react";
const App = () => {
const [value, setValue] = useState("");
useEffect(() => {
console.log("hello useEffect");
}, [value]); // value를 넣음
return (
<div>
<input
type="text"
value={value}
onChange={(event) => {
setValue(event.target.value);
}}
/>
</div>
);
}
export default App;
동영상 서비스가 종료되어 해당 콘텐츠를 재생할 수 없습니다.
클린업 cleanUp
: component가 사라졌을 때 무언가를 실행하는 과정
// src/App.js
import React, { useEffect } from "react";
const App = () => {
useEffect(()=>{
// 화면에 컴포넌트가 나타났을 때(mount) 실행하고자 하는 함수 넣기
return ()=>{
// 화면에서 컴포넌트가 사라졌을 때(unmount) 실행하고자 하는 함수 넣기
// clean up
}
}, [])
return <div>hello react!</div>
};
export default App;
도비 버튼을 누르면 useNavigate에 의해서 /todos로 이동하면서 HouseElf 컴포넌트를 벗어나게 될 것!
-> 화면에서 HouseElf 컴포넌트가 사라지고, useEffect의 return 부분이 실행됨
import React, { useEffect } from "react";
import { useNavigate } from "react-router-dom";
const HouseElf = () => {
const nav = useNavigate();
useEffect(() => {
return () => {
console.log(
"도비는 자유예요"
);
};
}, []);
return (
<button
onClick={() => {
nav("/todos");
}}
>
도비 버튼
</button>
);
};
export default HouseElf;
정리)
- useEffect는 화면에 컴포넌트가 mount 또는 unmount 됐을 때 실행하고자 하는 함수를 제어하게 해주는 훅이다
- 의존성 배열을 통해 함수의 실행 조건을 제어할 수 있다
- useEffect 에서 함수를 1번만 실행시키고자 할때는 의존성 배열을 빈 배열로 둔다
HW
stricmode
react Lifecycle
mount
unmount
추가로 알아보기!!!
'스파르타 개발일지' 카테고리의 다른 글
| 20221229 리액트 네이티브 시작! (0) | 2022.12.29 |
|---|---|
| 개발일지 20221213 리액트 숙련 강의 2 (0) | 2022.12.13 |
| 개발일지 20221210~11 todo-list 만들기 (0) | 2022.12.11 |
| 개발일지 20221208 리액트 입문 3 실습 (0) | 2022.12.08 |
| 개발일지 20221207 리액트 입문 2 (0) | 2022.12.07 |