Tech/ReactJS

· Tech/ReactJS
폼 데이터를 관리하다가 제어 컴포넌트와 비제어 컴포넌트에 대해 공부해보게되었다.📌 제어 컴포넌트와 비제어 컴포넌트제어 컴포넌트리액트 상태에 의해 값이 제어되는 컴포넌트이다. 사용자 입력값으로 자신의 상태를 관리하고 업데이트하고, 상태가 업데이트 될 때마다 컴포넌트는 리렌더링된다.폼 데이터가 상태에 저장되어 있어 데이터의 흐름이 명확하고, 로직 구현도 수월하지만, 빈번한 리렌더링으로 인해 불필요한 api 호출 등 자원 낭비가 발생할 수 있다.import React, { useState } from 'react';function ControlledComponent() { const [inputValue, setInputValue] = useState(''); const handleChange = (ev..
· Tech/ReactJS
📍 기존의 에러핸들링매번 try-catch로 api 통신 에러만 잡아냈을 뿐 에러처리에 대한 진지한 고민을 해본 경험이 없었다. 에러의 종류를 알고 커스텀 에러를 정의해 전역적인 에러 처리를 하고 싶다는 생각이 들었다. 📍 에러 핸들링 방법 선택에러 핸들링 방법은 여러가지가 있다 1. try-catch문- 특정 동작이나 함수 호출에 대한 에러 처리 2. promise catch문- 네트워크 요청 등의 비동기 코드에서 발생한 에러 처리 3. axios interceptor- 네트워크 에러 처리- axios 라이브러리 제공 기능 4. react-query onError- 데이터 fetching 중 발생한 에러 처리- react query 라이브러리 제공 기능 5. error boundary- 하위 컴포넌..
· Tech/ReactJS
📌 문제상황 - 사용자 경험 향상을 위해 상품 상세 페이지 로딩 시간을 줄이고자 상품 데이터 prefetch 도입- 전체 상품 조회 페이지에서 상품 썸네일 이미지에 hover 했을 때 상품 데이터 prefetch 하도록 설계- 마우스 움직임에 따라 불필요한 네트워크 요청 다량 발생  📌 원인 분석 const { handlePrefetchProduct } = usePrefetchProduct({ productId: data.id }); // prefetch 커스텀훅 const handleMouseEnter = () => { handlePrefetchProduct(); }; ;- 마우스가 잠깐이라도 스쳐지나간 경우 (ex 스크롤 시) 스쳐간 모든 상품에 대한 데이터 prefetch 동작 ..
· Tech/ReactJS
🚨 고민 발생해당 컴포넌트는 공통 컴포넌트로 만들어져있다.여러 곳에서 사용되기 때문에 공통 컴포넌트로 분리했던 건데,, 문제가 생겼다.사용처마다 스타일이나 요소 배치 등의 컴포넌트 요구사항이 조금씩 다르는 것이다. 결국 여러 조건을 걸 수밖에 없었고 아래와 같이 꽤 복잡한 공통 컴포넌트가 만들어졌다.const ProductBoardItem = forwardRef( ( { item, children, checkHandler, checkedItems, selectedCnt, isCart }, ref ) => { return ( { checkHandler( checked as boolean, sel..
· Tech/ReactJS
📌 문제상황// 실제 코드는 부가적인 기능으로 코드가 복잡하여 최대한 간소화한 코드를 예시로 사용했다 {[1, 2, 3].map((_) => ( 이름 가격 ))};- Grid 배치로 크기를 자동으로 설정한 grid 아이템 이미지의 로딩 전후로 리플로우 발생 이슈 발견- w-full 과 aspect-square로 높이와 너비 비율을 설정했다고 생각했기 때문에 리플로우 없이 로딩 될 것이라 생각했지만, 예상과는 다른 동작 결과를 보임  📌 원인 분석=>  aspect ratio을 1:1로 세팅해둔 것이 높이를 설정한 것이라 생각한 게 문제 - 높이가 명시적으로 정해진 것이 아니기 때문에 브라우저는 이미지를 로드하기 전까지 높이를 정확하게 알 수 없음. 즉, ..
· Tech/ReactJS
📍 문제상황장바구니 아이템을 선택한 후 결제까지 완료하면 선택했던 아이템들은 장바구니에서 삭제가 되는 것이 정상 동작이다. 그런데 내 프로젝트에서는 아이템들이 삭제되었다가 장바구니를 다시 열면 재생성되어있는 이슈가 발생했다.삭제된 아이템이 개수가 0인 상태로 재생성되어 있었던 것.. 뭐야 무서워.. 📍 원인 분석콘솔을 통해 이전 장바구니 스토어 아이템 id에 해당하는 상품 데이터(=products)가 남아있는 것이 문제인 것을 찾아냈다.결제 이후 로직은 대충 다음과 같다.1) 결제 성공2) zustand 장바구니 스토어 아이템 삭제3) 장바구니 스토어 아이템 id에 해당하는 상품 데이터(=products) fetch 쿼리 캐싱 무효화 지난 products가 렌더링되는 근본적인 이유는 캐싱 무효화가 동..
· Tech/ReactJS
🔎 비동기적으로 동작하는 setStatesetState로 상태 업데이트 후 예상처럼 값이 나오지 않는 경험을 여러번 했었다. 이유를 찾아보니 호출한 직후 상태가 바로 업데이트 되지 않을 수 있어 상태 업데이트 후 바로 상태값을 확인할 때 예상한 값이 나오지 않을 수 있다는 것이었다. 아래와 같은 방법을 통해 이 문제를 해결했었다.1) useEffect 훅을 사용하여 상태 변경 후에 다음 로직을 실행하도록 설계한다.useEffect(() => { console.log(value); }, [value])2) 이전 상태에 의존할 경우 함수형 업데이트를 통하여 처리한다. const increment = () => { setCount(prevCount => prevCount + 1);}; 🔎 비동기..
· Tech/ReactJS
검색어 입력 중 검색창 외부를 클릭하면 연관 검색어 창이 닫히도록 구현해야 할 일이 생겼다 비슷한 경험으로 과거 모달을 띄우고 모달 외부를 클릭하면 모달이 닫히도록 구현한 적이 있는데, 그때는 어두운 불투명 오버레이 컴포넌트를 깔고 오버레이 컴포넌트에 onClick 이벤트 핸들러를 할당하여 클릭 이벤트가 발생하면 모달을 닫히는 동작으로 간단하게 구현할 수 있었다. 이번에도 동일한 방법으로 투명 오버레이를 깔아 구현해볼까 생각했으나 연관 검색어 창이 활성화 된 상태에서도 지도 확대 축소나 스크롤 등의 이벤트는 정상 동작 해야했기 때문에 불가능하다고 판단하였다. 💭 생각한 두가지 방법 그래서 생각해본 두가지 방법..! 우선 연관 검색어 창이 열려있는 지 닫혀있는지를 boolean으로 나타내는 state값을 ..
· Tech/ReactJS
📌 구현화면 버튼을 누르면 새로운 input이 생기고, UX를 위하여 새로 생긴 input 창에 바로 focus 되는 방식으로 동작하기를 원했다. 📌 구현내용 1. input Ref 만들기 questions은 나열하는 질문들의 값을 담는 state이고, lastInputRef는 가장 마지막의 input 값을 담기 위한 ref이다. map 함수를 사용하여 questions를 컴포넌트의 인자에 담아 렌더링 시킨다. 이때 lastInputRef도 인자로 담아 보낸다. 이렇게 하면 모든 질문의 input의 값을 거쳐서 결국 마지막에 렌더링 되는 마지막 input의 값이 lastInputRef에 담기게 된다. const [questions, setQuestions] = useState(); const lastIn..
· Tech/ReactJS
구현 화면 태그를 입력한 뒤 엔터를 누르면 등록되는 방식으로 구현하였다. 태그의 X표시를 누르면 태그가 삭제된다. 구현과정 1. 기본 구조 생성 우선 기본적인 디자인을 잡아보자. 입력한 태그를 담을 tags state를 만들어 map 함수를 활용해 뿌린다. const [tags, setTags] = useState([]); {tags.map((tag, idx) => ( {tag} × ))} ; 사용한 스타일 컴포넌트의 css는 다음과 같다. const TagInputContainer = styled.div` ${flexICenter} flex-wrap: wrap; gap: 0.5em; background-color: ${(props) => props.theme.colors.gray.xxs}; paddin..
· Tech/ReactJS
페이지가 들어왔을 때 로딩 메세지가 보이고 코인들이 나열되면 로딩메세지를 숨김 import { useEffect, useState } from "react"; function App() { const [loading, setLoading] = useState(true); const [coins, setCoins] = useState([]); useEffect(() => { fetch("https://api.coinpaprika.com/v1/tickers") .then((response) => response.json()) // response를 받아서 response.json 리턴 .then((json) => { //리턴한 json을 사용하여 setCoins(json); //coins에 json데이터 삽..
· Tech/ReactJS
todo 입력받기 import { useEffect, useState } from "react"; function App() { const [toDo, setToDo] = useState(""); const [toDos, setToDos] = useState([]); const onChange = (event) => setToDo(event.target.value); const onSubmit = (event) => { event.preventDefault(); //기본동작 제어 if (toDo === "") { return; } setToDos((currentArray) => [toDo, ...currentArray]); // state를 직접 수정할 수는 없음 setToDo(""); }; return..
· Tech/ReactJS
* 리액트 앱을 사용한 실습 * create-react-app으로 간단하게 리액트 앱을 설치한다. 리액트 앱 내에서 prop-types를 사용하고 싶다면 따로 설치하여 import 시켜줘야 한다. 그리고 css 적용 시 컴포넌트별로 css파일을 만들어 모듈화시켜줄 수 있다. .module.css 파일을 생성하고 import 하여 사용하면 된다. 최초 렌더링에만 코드가 실행되게 하는 방법 : useEffect() state값이 변화되어 리렌더링 되면 모든 코드가 재실행된다. 이때 API를 사용했을 때처럼 한번만 받아도 될 정보의 경우에도 리렌더링 할 때마다 계속 호출된다. useEffect()를 사용하면 특정 코드가 최초로 render할 때만 실행되게 할 수 있다. useEffect() 사용 예시는 아래와..
· Tech/ReactJS
Props는 부모 컴포넌트가 자식 컴포넌트에게 데이터를 보내는 방식이다. 예를 들어 동일한 스타일의 버튼 여러개를 생성할 때 하나의 버튼 컴포넌트를 생성하고 데이터를 props로 받으면 쉽게 재사용 할 수 있다. 컴포넌트 props는 컴포넌트의 첫번째이자 유일한 인자이다. props에 여러개의 데이터를 모두 포함시키면 데이터는 오브젝트 형식으로 담아지게 된다. 컴포넌트 내에서 데이터를 불러올 때는 props.특정값 으로 사용할 수 있지만 처음부터 props 중에서 특정 값만 가져오고 싶다면 Btn(props) 대신 Btn ({ 특정값 })라고 하면 된다. props로 받는 함수 props에는 다양한 string, boolean값은 물론 function까지 담을 수 있다. props로 전달된 함수는 이벤트..
· Tech/ReactJS
버튼을 누를 때마다 올라가는 counter 수와 같은 바뀔 데이터를 어떻게 담아야 할까? 컴포넌트는 한번만 렌더링이 되기 때문에 counter 변수의 값은 바뀌어도 UI의 counter은 바뀌지 않는다. 그렇다면 어떻게 할 수 있을까? 직접 리렌더링 시켜주는 방법 ( 실제로 쓰진 않고 단지 원리를 이해하기 위함 ) 이 방법은 실제로 사용하지는 않고 단지 원리를 이해하기 위함이다. 이 방법에서는 UI를 변경해주기 위해서 우리가 만든 container 컴포넌트를 counter 수가 바뀔 때마다 리렌더링 시켜준다. 이때 다시 렌더링 하더라도 리액트가 알아서 바뀐부분만 리렌더링 시켜준다. 리액트JS는 바뀐 부분만 리렌더링 해주기 때문에 효율적이다. 리액트 JS의 렌더트리는 단계가 최적화 되어있다. 바닐라js는 ..
닝닝깅
'Tech/ReactJS' 카테고리의 글 목록