react 개발자가 자주 겪는 어려움 5가지

Q&A 큐레이션

1. 리액트 props, state

프론트엔드 개발자를 꿈꾸고 있는 미래지망생 입니다 지금은 국비 학원을 다니면서 html css js를 어느정도 배우고 React를 10일정도 배우면서 props state react-hooks를 배우고 다음주 월요일 부터 개인 프로젝트가 들어가게 되었습니다(학원스케줄) 저는 프로젝트 주제가 마땅히 없어 신한카트 페이지를 만들려고 하고있습니다 근데 막상 하려고 하니 컴포넌트는 나누지만 안에 들어있는 내용은 그냥 쌩 html로 작성한거 같아 전혀 react를 활용 못하고 있는거 같습니다 데이터가 변하지 않는것은props로 데이터가 잘 변하는 것은 state로 지정하라고 들었는대 막상 하니 뭐가 잘 변하는지 잘 안변하는지 이렇게 html 작성하드시 하는게 맞는지 어떻게 하면 좋을까요


답변

안녕하세요~ React로 개발하시면서 React의 활용에 대해 고민하고 더 잘 사용하려고 하신다니 대단하신 것 같습니다👍 제가 작성자분의 코드를 모르기 때문에 자세한 피드백은 드릴 수 없지만 글에 남겨주신 props와 state에 대해서 답변드리겠습니다. | 데이터가 변하지 않는것은 props로 데이터가 잘 변하는 것은 state로 지정 -> props와 state는 작성해주신 기준으로 나누는게 아닙니다. 변하는 데이터도 props로 넘겨줄 수 있기 때문이에요. props는 부모가 자식 컴포넌트에 전달하는 데이터의 개념이고, state는 상태를 갖는 데이터로 정의됩니다. 따라서 props와 state의 개념을 명확히 공부하는게 필요할 것 같아요. 세부적으로 공부할 키워드를 말씀드리면 props: props drilling, props에 전달하는 데이터에 대해 유의할 점 (참조 동일성) state: react에서 state는 무엇인지, useState는 어떻게 구현되있는지 React를 공부하면서 궁금한점이 생기면 많은 질문 부탁드려요! 저도 배우는 자세로 답변드리겠습니다

모두 보기

2. React에서 children, child 컴포넌트에 props를 넘겨주는 방법

child 컴포넌트에 props를 넘겨주는 방법이 있을까요? <Parent> <Child /> <Child /> <Child /> </Parent> 이런 구조인데 Child 컴포넌트가 부모 컴포넌트의 값을 고정으로 받아야 합니다. 하나하나 props로 넘겨주지 않고 Parent 컴포넌트안에서 props로 넘겨주고 싶은데 어떻게 하면 좋을까요?


답변

| Parent 컴포넌트안에서 props로 넘겨주고 싶은데 어떻게 하면 좋을까요? 이 말로 미루어보아 Children을 props로 받는 구조인 것 같습니다. React.cloneElement 함수를 사용해서 고정된 값을 넘겨주면 될 것 같습니다. children 컴포넌트들이 특정 key, id 그리고 클릭 여부(defaultActive)를 받는 상황이라고 하면 다음과 같이 작성하면 될 것 같아요 import {cloneElement} from "react" const Parent = ({ id, defaultActive, children }) => { const cloneChildren = children.map((el, index) => { return cloneElement(el, { key: `key${index + 1}`, id, active: defaultActive === index, }); }); return <div>{cloneChildren}</div>; };

모두 보기

3. React에서는 이벤트 버블링이 발생하지 않나요?

javascript를 배울 때 부모, 자식 컴포넌트가 같은 이벤트를 핸들링하고 자식 컴포넌트의 이벤트가 실행되면 버블링이 발생하는걸로 알고있습니다. ex) p태그를 클릭하면 p -> div -> form으로 alert이 세번 실행됨. <form onclick="alert('form')">FORM <div onclick="alert('div')">DIV <p onclick="alert('p')">P</p> </div> </form> React에서는 왜 이벤트 버블링이 발생하지 않나요? (몇 번 e.stopPropagation으로 막아주긴 했는데 기본적으로는 동작하지 않는 것 같아요) React로 실무를 하고있지만 한번도 이벤트 버블링을 신경쓴적이 없어서 문득 궁금해졌네요.


답변

저도 예전에 궁금해서 찾아봤는데 카카오 기술 블로그에서 관련된 내용의 글을 발견해서 공유드립니다. https://fe-developers.kakaoent.com/2022/220908-react-event-and-browser-event/ 간단히 요약해보면 - 리액트 이벤트는 브라우저 이벤트를 래핑한 이벤트임 - 리액트에서 정의한 이벤트는 리엑트의 root에 붙음 - 리액트에서 정의한 이벤트가 root에 붙기 때문에 리액트 JSX 태그에 on~ 으로 작성한 이벤트들은 버블링을 타지 않음 (다 한곳에 있기 때문에, 계층이 발생하지 않는다) 질문자분이 남겨주신 '가끔씩 e.stopPropagation으로 버블링을 막아줬던 경우'는 window에 이벤트 리스너를 직접 달아주는 등 계층으로 이벤트가 발생했던 상황이라고 추론해볼 수 있겠네요. 혹시 틀린 부분이 있으면 수정 부탁드립니다:)

모두 보기

4. Maximum update depth exceeded 에러 해결 방법

콘솔에 "Maximum update depth exceeded. This can happen when a component calls setState inside useEffect, but useEffect either doesn’t have a dependency array, or one of the dependencies changes on every render." 라는 에러가 표시되면서 해당 컴포넌트가 무한히 렌더링 되고 있습니다. 문제 원인과 해결 방법을 아시는 분이 계실까요? 코드 간단히 요약해서 첨부합니다.


답변

setordercart 할때 조건을 걸어줘야 할것같네요 의존성 배열에 들어가있는 값이 리렌더링이 발생 할때마다 변경되는것으로 인지해서 셋을 계속 호출 하는 상황입니다 아니면 의존성 배열에 해당하는 데이터를 usememo 나 usecallback 으로 감싸줘야 할것같네요

모두 보기

5. React.memo로 감싼 컴포넌트가 계속 렌더링 됩니다.

부모 컴포넌트에서 map으로 자식 컴포넌트를 렌더링 하고 있습니다. 자식 컴포넌트가 받는 props에 변화가 없어서 React.memo로 감쌌는데 컴포넌트가 계속 렌더링 되고 있습니다. props도 확인했습니다.. props는 {userId:number, onClick: () => {history.push(...)}} 이런식으로 넘겨주고 있습니다. 해결하고 싶은데 도움주시면 감사하겠습니다!


답변

onClick으로 전달하는 () => history.push 함수로 인해 리렌더링 되는 것 같습니다. 참조 동일성의 개념을 아셔야하는데요, 리액트는 값을 비교하여 리렌더링 할 때 얕은 비교(Shallow Compare)를 합니다. 얕은 비교는 객체, 배열, 함수와 같은 참조 타입들을 실제 내부 값까지 비교하지 않고 동일한 메모리 값을 사용하는지(동일 참조인지)를 비교합니다. map으로 자식 컴포넌트가 생성될 때 새로운 메모리 값을 사용하는 함수가 onClick으로 전달되어 메모이제이션을 하지 못하고 리렌더링 되는 현상같아요. React.memo를 사용한다면, 함수를 props에서 바로 정의하지 말고, 부모 컴포넌트안에 정의한 뒤 useCallback으로 감싸서 전달하면 리렌더링이 발생하지 않을 것 같습니다. 코드로 간략하게 작성해봤습니다. const handleChildClick = useCallback(() => { history.push(...) }, []) <Child onClick={handleChildClick}/>

모두 보기