일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- 성수볼거리
- 객체지향프로그래밍
- 직장인점심
- Java
- 헤드퍼스트
- 직장인
- 책너두
- 깨끗한코드
- 성수핫플
- 성수맛집
- 헤드퍼스트디자인패턴
- 코딩
- 디자인패턴
- 주니어개발자
- 개발자
- 상속
- 책읽기
- DesignPattern
- 독서일지
- IntelliJ
- 성수직장인
- 클린코드
- 독서
- JavaScript
- 오브젝트
- JAVA개발자
- 성수
- Linux
- docker
- 객체지향
- Today
- Total
닭발개발
렌더링 rendering 본문
나는 리액트에서 렌더링 이야기만 나오면 지레 겁을 먹는다.
가장 어려운 부분이기 때문이다.
[상황]
부모 - 자식 컴포넌트가 있으면 부모에서 버튼 클릭 시, 자식 컴포넌트가 바뀌어야 한다.
그런데 렌더링이 안되고 자식 컴포넌트가 바로 바뀌지 않음.
우리는 렌더링이 필요한 상황!
그런데 구글링 해보면 다 렌더링을 막는 글들 뿐이었다.
해결한 방법은 쉬운 방법.
[해결]
보여줄 값이 바뀌었다는걸 자식 컴포넌트가 알 수 있도록 "값이 바뀜"을 state로 관리한다.
// 부모가 자식에게 우리 변했어! 라고 알려줄 힌트
const [initPage, setInitPage] = useState(false);
useLayoutEffect(() => {
setInitPage(true);
});
if(수정이 성공하면) {
setInitPage(false);
}
자식 컴포넌트에 전달!
{initPage && <SelectBoxNativeComponent type='roleManagement' onAction={onAction} />}
문제는 이렇게 쉽게 해결되었지만,
렌더링에 대해 조금 공부했다.
1. React의 작동 원리
React Element의 생성 순서 및 리렌더링 흐름을 알 수 있는 예제 )
// App.js
// import 생략
function App() {
console.log("자식 렌더링 시작");
useEffect(() => {
console.log("자식 리렌더링");
});
return(
<Parent><Child/></Parent>
)
};
export default App;
// 부모 컴포넌트 (Parent.js)
// import 생략
export const Parent = (({children}) => {
console.log("부모 렌더링 시작");
const [counter, setCounter] = useState(0);
useEffect(() = > {
console.log("부모 리렌더링");
});
return (
<div>
<h1>
부모
</h1>
<button onClick={() => setCounter(counter + 1)}>
부모버튼 {counter}
</button>
{children}
</div>
);
};
// 자식 컴포넌트 (Child.js)
// import 생략
export const Child = () => {
console.log("자식 렌더링 시작");
useEffect(()=> {
console.log("자식 리렌더링!");
});
return (
<div>자식</div>;
)
};
1. render 함수는 가상돔 (react virtual DOM) 계층에서 아래와 같이 순서대로 호출된다.
App -> Parent -> Child
2. react element는 계층의 맨 아래부터 반대 순서로 마운트 된다.
- 마운트 순서
Child -> Parent -> App
*** 부모 요소는 자식요소를 생성하는 요소가 아니다.!! ***
"컴포넌트의 상태(state)가 변하면, 컴포넌트의 리렌더링을 발생(trigger)시킨다."
[ 컴포넌트가 리렌더링 될 때 ]
- 자신의 상태(state)가 변경될 때
- 부모 컴포넌트가 리렌더링 될 때
- 자신이 전달받은 props가 변경될 때
- forceUpdate 함수가 실행될 때
[ 리렌더링 방지템 React.memo ]
React.momo는 고차 컴포넌트(HOC)이다.
고차 컴포넌트(HOC)란? 어떤 컴포넌트를 가져와서 새로운 컴포넌트를 리턴하는 함수.
사용법)
컴포넌트를 만들고 나서 감싸주기만 하면 됨.
컴포넌트의 props가 바뀌지 않았다면 리렌더링 되지 않게 가능!
props를 메모리에 저장하고 동일한 입력이 반복되서 발생하면 캐시된 출력을 반환한다.
// memo를 사용하여 코드 수정
// App.js
// import 생략
function App() {
return(
<Parent><Child/></Parent>
)
};
export default App;
// Parent.js
// import 생략
// 부모 컴포넌트 (Parent.js)
// import 생략
export const Parent = (({children}) => {
const [counter, setCounter] = useState(0);
return (
<div>
<h1>
부모
</h1>
<button onClick={() => setCounter(counter + 1)}>
부모버튼 {counter}
</button>
{children}
</div>
);
};
// Child.js
// import 생략
export const Child = () => {
const [inPutText, setInputText] = useState("");
const handleChange = event => {
setInputText(event.target.value);
};
return (
<>
<div>자식</div>
<input style={{maginBottom: "0.5rem"}} onChange={handleChange}>
<ChildChild/>
</input>
</>
)
}
// ChildChild.js
// import 생략
export const ChildChild = () => {
const [inputText, setInputText] = useState("");
const handleChange = event => {
setInputText(event.target.value);
};
return (
<>
<div>자식의 자식</div>
<input onChange={handleChange} />
</>
);
}
--> 코드 실행 결과
"자식"의 state가 바뀌기 때문에 자식이 리렌더링 되고, "자식의 자식"은 부모 컴포넌트가 리렌더링 되기 때문에 아무것도 안했지만, 같이 리렌더링 됨.
"자식" 컴포넌트가 모두 리렌더링 되면서 자식과 자식의 자식이라는 고정된 텍스트까지 리렌더링 된다.
--> 리렌더링 최적화 하기 : "자식" 컴포넌트와 "자식의 자식" 컴포넌트를 React.memo로 감싸면 된다.
// Child.js
export const Child = React.memo(() => {
// 생략...
});
// ChildChild.js
export const ChildChild = React.memo(() => {
// 생략 ...
});
** 리액트 공식 문서 **
This method only exists as a performance optimization. Do not rely on it to "prevent" a render, as this can lead to bugs.
>> React.memo를 성능 최적화 목적으로 사용해야지, 렌더링을 방지할 목적으로 사용하면 버그를 만들 수 있다.
출처
https://code-masterjung.tistory.com/67
[React] 리액트 (리)렌더링, React.memo
React는 어떻게 작동할까? 먼저 아래 있는 앱과 부모, 자식 컴포넌트로 구성된 예제를 보자. // App.js import React, { useEffect } from "react"; import { Parent } from "./Parent"; import { Child } from "./Child"; function App() {
code-masterjung.tistory.com
'React' 카테고리의 다른 글
[Error] useRoutes() may be used only in the context of a <Router> component. (1) | 2023.08.16 |
---|---|
[Error] Can't resolve '@mui/material/TextField' (0) | 2023.08.09 |
[오류][React Native/android] validateSigningDebug FAILED (0) | 2023.04.24 |
React에서 텍스트 줄바꿈하기 (2) | 2023.03.30 |
&& 조건문 (2) | 2023.03.10 |