전체 글 15

[개발일지]랜덤으로 결과 보여주기

사용자의 응답에 맞게 결과를 랜덤으로 보여주는 서비스를 제작 중이다. 원하는 화면을 위해 구현되어야할 것은 1. 응답별 결과 매칭 설계 2. 사용자의 응답을 저장 3. 응답과 결과를 매칭하는 로직 이 세 가지가 필요하다. 1. 응답별 결과 매칭 목록은 기획을 담당한 팀원과 작성했다. 아래와 같은 화면이 구현되어야 하기 때문에, 결과 응답으로 받을 json의 프로퍼티를 다음과 같이 구성하였다.(※ 서브 텍스트는 공통되므로 응답 값으로 받아오지 않는다.) 타입스크립트를 활용한 프로젝트가 아니기 때문에, 프로퍼티에만 집중하기 쉽도록 선언하였다. { id: number; activityName: string; characterGroup: characterGroupType; isOutside: boolean; i..

[공식문서 읽기]함수형 업데이트로 멀티 폼 유효성 검사를 한 번에 해보자.

🔗 https://react.dev/learn/queueing-a-series-of-state-updates 문서를 읽고 문제를 해결한 경험을 정리한다. Queueing a Series of State Updates – React The library for web and native user interfaces react.dev | 반복문 안에서 setState를 여러 번 호출할 경우 함수형 업데이트를 해야 원하는 결과를 얻을 수 있다. 문제 상황 submit 이벤트가 발생했을 때 유효성을 검사하는 회원가입 폼을 구현하다가 state로 관리하고 있던 에러 메시지가 제대로 출력되지 않는 상황이 발생했다. 제출을 하면, 나머지 폼도 공백이라 에러메시지가 출력되어야 하는데 가장 마지막 유효성 폼인 githu..

카테고리 없음 2023.09.23

[TailwindCSS]동적 클래스네임 짓기

기본적인 투두리스트에 다크 모드를 적용하려는데 정적으로 'dark'를 명시하지 않으면 바뀌는 상태값대로 클래스명에 반영이 되어도 정적 빌드할 때 클래스명을 읽어오지 못하는 현상으로 다크모드가 적용되지 않는 문제가 발생했다. 당시 문제가 되는 코드: | 동적 변수 `theme`을 클래스명에 바로 추가 => 동적 클래스네임 생성 https://tailwindcss.com/docs/content-configuration#dynamic-class-names Content Configuration - Tailwind CSS Configuring the content sources for your project. tailwindcss.com 공식문서에서 권장하지 않는 클래스명 생성 방법이 내가 작성한 코드와 똑같았..

카테고리 없음 2023.09.18

[라이브러리]DND-kit으로 drag&drop을 구현해보자

DND-kit 라이브러리로 버튼을 누르면 모달도 열리고, 특정 날짜에 drag&drop 가능한 캘린더를 구현해보자. DND 라이브러리를 사용한 이유는 '충돌감지 알고리즘(Collision detection algorithms)'과 '센서 제약(Activation constraints)'이 구현돼있어서다. draggable 한 컴포넌트(예: button)을 눌렀을 때 바로 드래그 가능한 컴포넌트가 아니라 모달 open의 기능도 수행해야 하므로, 드래그를 감지하는 센서를 제약해야 했다. DND-kit으로 컴포넌트를 drag&drop 가능하도록 만들어보자. 1. drag&drop을 사용하려면 우선 로 감싸야 한다. {allDay.map((day, idx) => ( { const scheduleDate = ne..

카테고리 없음 2023.09.11

[공식문서 읽기]Updating Objects in State

| React에서 state로 관리하고 있는 객체를 업데이트하려면 직접 객체를 수정하는게 아니라 새로운 객체를 만들어 전달해야 한다.(replace) 리액트로 달력 만들기 예제를 학습하다가 const date = new Date(nowDate.getTime()); 위 코드와 const [nowDate, setNowDate] = useState(() => new Date()); const newDate = nowDate; 아래 코드의 차이를 알 수가 없었다. 그 차이는 `Date.setMonth()` 메서드를 사용한 뒤 상태 변경 함수를 실행한 후에 발생했다. 첫 번째 코드는 리렌더링을 트리거하여 바뀌는 화면을 보여주었지만, 이전 상태 변수 객체를 참조하고 있던 두 번째 코드는 리렌더링을 트리거하지 않는다..

카테고리 없음 2023.08.21

[React]customHook으로 투두리스트 편집mode를 만들어보자

투두리스트의 편집 모드에서는 편집 모드가 아닌 상태에서 지원했던 추가, 수정(할 일 체크), 삭제 기능을 모두 지원해야 했다. 동시에 수정되었지만, 저장하지 않고 편집 모드를 종료할 수 있도록 수정되기 전 투두리스트의 값도 여전히 가지고 있어야 했다. 투두리스트의 추가/삭제/수정 로직은 일반 모드/편집 모드 둘다 동일하므로, 데이터만 다르게 사용하는 로직 재사용을 위해 customHook으로 추출하기로 했다. customHook 사용 전/후 코드 비교를 위해 github에 커밋한 다음 비교했다. 🔗 1. customHook 사용 이전 투두리스트가 가지고 있는 전체 데이터는 `data`가 객체 배열의 형태로 관리하고 있다. `App.jsx` function App() { const [data, setDat..

카테고리 없음 2023.08.13

[React]리스트에 아이템 추가하고, 최신 아이템으로 스크롤 이동해보자.

투두리스트에 스크롤이 생겼을 때 할 일을 추가하면 추가한 일로 스크롤이 이동하여 사용자가 방금 추가한 할 일을 바로 확인할 수 있도록 하고 싶었다. 1. useEffect 사용 처음엔 useLayoutEffect() hook 으로 '새로 추가된 아이템이 반영된 리스트의 높이를 미리 계산해야 하지 않을까' 했지만, useEffect() hook 만 사용해도 문제없이 잘 동작했기 때문에, useEffect() hook 을 사용하였다. 할 일이 추가되거나, 삭제될 때 동작이 달라야 하므로 prop으로 내려받고 있는 data의 길이를 dependency로 설정하였다. 2. useRef 사용 사용자가 할 일을 추가하거나 삭제할 때 할 일을 렌더링하고 있는 리스트의 길이가 변화하므로, useRef로 해당 DOM에 ..

카테고리 없음 2023.08.05

제어 컴포넌트 vs 비제어 컴포넌트

https://goshacmd.com/controlled-vs-uncontrolled-inputs-react/ 번역 비제어 | 제어 되지 않은 input은 기존 HTML 양식 입력과 같습니다. 비제어 input은 입력한 내용을 기억합니다. 비제어 입력값은 ref 로 가져올 수 있습니다. 예를 들어 버튼의 onClick 핸들러에서: 즉, 필요할 때 필드에서 값을 '가져와야'합니다. 이는 폼이 제출될 때 발생할 수 있습니다. 위와 같은 방식이 폼 입력을 구현하는 가장 간단한 방법입니다. 실제로 간단한 양식이거나 React를 배울 때 이 방식을 사용하는 것은 분명 유효하지만, 그다지 강력하지는 않으므로 제어된 입력을 살펴봅시다. 제어 | 제어된 input은 현재 값을 prop으로 받아들이고, 그 값을 변경하는..

카테고리 없음 2023.07.30

[공식문서 읽기]Keeping Components Pure

1. Fix a broken clock | 자정부터 오전 6시까지는 'night' className을 줘서 시계 색상 반전 시키기 내가 쓴 답 export default function Clock({ time }) { let hours = time.getHours(); if (hours >= 0 && hours = 0 && hours ( {story.label} ))} {'Create Story'} ); } React solution | export default function StoryTray({ stories }) { return ( {stories.map(story => ( {story.label} ))} Create Story ); } 시계가 업데이트될 때마다 'Create Story'가 두 번..

카테고리 없음 2023.07.23

createBrowserRouter()로 router를 관리하자

createBrowserRouter()는 라우터를 객체로 관리한다. 다음과 같이 관리할 라우터 객체의 타입을 선언해주었다. 장바구니 프로젝트에는 Navbar가 모든 페이지에 포함되기 때문에 Navbar 컴포넌트가 포함된 페이지를 메인 레이아웃으로 두기로 한다. 메인 레이아웃 컴포넌트를 라우터 객체에서 관리할 수도 있겠지만, 그렇게 되면 다른 페이지들이 메인 레이아웃 컴포넌트의 children 프로퍼티에 들어가야 해서 재사용하기 어려울 것 같았다. 그래서 createBrowerRouter() 를 사용해 가공된 라우터 객체 배열을 전달하기로 했다. 현재는 모든 페이지에 Navbar가 들어가지만, 이후 Navbar가 없는 페이지가 생길 경우의 확장성을 고려해 main 프로퍼티를 optional하게 지정하여 작..