[Next.js] 컴포넌트간 데이터 넘기기, 리랜더링방지
1. 하위 컴포넌트에서 상위 컴포넌트로 props 넘기기
2. 넘겨진 props 에 의해 상위 컴포넌트 전체 리랜더링 되는거 막기
먼저 설명할 컴포넌트의 구조를 그림으로 그려보면,
이런식으로 상위 A 컴포넌트 안에 B, C, D 를 두었다 (select box 나 input, date picker 같은 컴포넌트)
이때 B에서 state를 변화했을때 A 에서 이를 어떻게 알까?
Angular 같은 경우는 하나의 service 에 변수를 빼서 그 변수를 구독하는 식으로 여러 컴포넌트에서 썼었는데 리액트는 어떻게 사용하는 지 모르겠어서 구글링을 해보았다.
상위 컴포넌트에서 state를 정의해두고 useState 함수에 해당하는 값을 하위 컴포넌트로 넘겨주면 된다고 한다.
//상위컴포넌트, 도식화 A
const [select, setSelect] = React.useState();
console.log("select is "+select);
...
return(//propFunction은 아무 이름이나 하면 됨
<ComponentB propFunction={setSelect} />
);
//하위컴포넌트, 도식화 B
...
return(//rsuit에 Cascader 라이브러리 컴포넌트를 사용했음. onchage 에 props로 넘어온 함수 넣어줌
<div>
<Cascader onchange={props.propFunction} />
<div>
);
이런식으로 상위 컴포넌트 A 안에서 B 컴포넌트 호출 시 setState 에 해당하는 함수명을 넘겨주고, 하위 컴포넌트 B 안에서 해당 함수를 onclick 이나 onchange 등 때에 따라 호출 하도록 하면 해당 state가 B에서 변경 되고 A로 타고 올라간다.(타고 올라간다고 표현하는게 맞나싶지만 설명하기 쉽게 그렇게 표현)
여기까지했을 때 A 에서 콘솔 로그에 잘 찍히는걸 볼수있는데 문제가 하나 발생함.
A 단에 모든 컴포넌트가 리랜더링 되는 문제가 발생..
B에서 state가 바껴 A의 setState 해당하는 함수가 호출되므로 A단 컴포넌트가 전부 리랜더링 되는게 맞다. 이론적으로는
그치만 C와 D 컴포넌트가 table 이나 chart 같이 많은 데이터들을 불러와야 하는 컴포넌트 인 경우 이런식으로 불필요하게 리랜더링 시키면 안되기에. 다시 구글링 시작.
useMemo 를 사용하면 원하는 state 가 변경됐을 경우만 리랜더링 할 수 있도록 막을 수 있다고 한다.
A 단에서 C와 D를 호출 하는 소스를 useMemo 안에 넣어서 수정했다.
//도식화 A
//변경 전 소스
const [select, setSelect] = React.useState();
console.log("select is "+select);
return (
<div>
<ComponentB propFunction={setMeterType} />
<ComponentC data={data1} />
<ComponentD data={data2} />
</div>
);
//도식화 A
//변경 후 소스
const [select, setSelect] = React.useState();
console.log("select is "+select);
const memoComponentC = useMemo(() => {
return <ComponentC data={data1} />
},[data1]); //data1이 바꼈을때만 리랜더링
const memoComponentD = useMemo(() => {
return <ComponentD data={data2} />
},[data2]); //data2가 바꼈을때만 리랜더링
return (
<div>
<ComponentB propFunction={setMeterType} />
{memoComponentC}
{memoComponentD}
</div>
);
C와 D를 useMemo로 리턴받아 랜더링 해주니까 B가 바뀌어도 C와 D는 새로고침 되지않게 되었다!
인터넷 찾아보니까 useMemo는 거의 useCallback 과 함께 쓰던데 이건 좀 더 스터디 해봐야할듯하다