목록분류 전체보기 (297)
가수면
아래와 같이 코드를 추가해줌. // package.json "build": "GENERATE_SOURCEMAP=false react-scripts build", "winBuild": "set \"GENERATE_SOURCEMAP=false\" && react-scripts build", build는 일반적인 리눅스 적용이고 윈도우 오류나는 경우가 있어 winBuild를 추가해줌. 코드를 추가해주면 배포 시 소스맵이 보이지 않는 것을 확인할 수 있다.
![](http://i1.daumcdn.net/thumb/C150x150/?fname=https://blog.kakaocdn.net/dn/bmvrLw/btrXOwntBEi/U3YK4Ei4QVLQ8Aw7TUQYp0/img.png)
코드 리팩토링 도중 전역 상태 관리는 리액트 쿼리로도 가능한데(당시 푸터에서 데이터를 저장하고 뽑아쓰면 리렌더링이 일어나는 것을 확인해서 착각함) 그럼 리덕스는 안 써도 되는 것 아닐까 하는 생각에서 실험 시작. 왼쪽처럼 dispatch를 사용하여 전역으로 관리하던 값을 쿼리로 교체해보았다. 그러나 예상과 달리 쿼리에 저장된 값은 바뀌고 있는데 콘솔이 찍히질 않는다. 이 말은 곧 렌더링이 일어나지 않는다는 소리. 값이 바뀌었으니 화면이 바뀌어야 하는데 역시나 화면이 바뀌질 않았다. 여기서 의문. 푸터에 박혀있는 아이콘은 클릭 시 변경되는 값에 따라 초록색으로 잘 바뀌고 있는데, 대체 왜 같은 onClick함수에 담겨 있는 diaryViewState를 사용하는 다이어리는 바뀐 값에 따라 렌더링이 일어나고 ..
최적화와 컴포넌트를 쪼개는 것에 대한 고민은 기획 단계에서부터 했었던 고민들이다. 그러나 기능부터, 기능부터라며 차일피일 미뤄왔던 것들... 이젠 그 작업이 코앞으로 다가온 것이다! light house 점수가 낮게 나와 걱정이 크지만...리팩토링 하다보면 나아지겠지...? 이번 주 한 작업 컴파운드 패턴의 모달 만들기 수정 되거나 추가 된 디자인 반영 일기 설정 페이지 기능 구현 프로젝트에 PWA 적용 추가된 달력 기능 작업 중 트러블 슈팅 - 지난 주 모달이 자꾸 닫히던 오류 원인 해결 - 지난주 어디를 눌러도 모달이 꺼지던 문제가 발생했었는데, 모달을 새로 만들어 해결은 했었지만 끝내 찾지 못했었던 원인을 찾음. 부모 컴포넌트로부터 전파된 이벤트가 적용되던 것이었음. - 도움을 받은 블로그 - ht..
![](http://i1.daumcdn.net/thumb/C150x150/?fname=https://blog.kakaocdn.net/dn/bO3TUT/btrXgq9T2Jp/DNHebeo5a0ruzUd1xc0OKk/img.png)
Compound 합성. 하나의 컴포넌트를 잘게 쪼개 레고 블럭처럼 조립해 쓴다니, 이 얼마나 리액트 컨셉에 잘 맞아떨어지는 패턴이란 말인가 내가 컴파운드 패턴을 공부하기 시작한 데에는 몇 가지 이유가 있었다. 첫째, 중복된 코드들로 인해 난잡해진 팀 프로젝트의 코드 수를 대폭 줄일 필요가 있었으며, 둘째, 중구난방으로 쓰이고 있는 모달들을 통합할 필요가 있었고, 셋째, 팀원들의 부탁도 있었던 데다가, 넷째, 현업에서 많이 쓰이는 패턴이라는 소리를 어디선가 들은 것에 더해, 다섯째, 클린해보였다...! 컴파운드 컴포넌트 이렇게 쓰는 거 맞음? 나는 바로 코딩에 들어갔다. 뚝딱! 아주 기본적인 컴파운트 패턴의 모달 컴포넌트가 완성되었다.(거의 이틀이 걸렸다.) notClose를 주냐 안 주냐에 따라 배경을 ..
![](http://i1.daumcdn.net/thumb/C150x150/?fname=https://blog.kakaocdn.net/dn/byuUr3/btrW2tqXwjp/bRLG0um2JWyjeXORrU5pe0/img.png)
기존의 프로젝트에 PWA를 적용하는 방법을 알아보자.리액트에서 적용하기1. 파일 가져오기빌더 없이도 PWA 템플릿을 이용하면 간편하게 기존 프로젝트를 PWA로 탈바꿈시킬 수 있다.npx create-react-app my-app --template cra-template-pwa원하는 경로에 새롭게 CRA를 해준 뒤, 새롭게 생성된 프로젝트의 src 폴더에 있는"service-worker.js" 와 "serviceWorkerRegistration.js" 파일을 기존 프로젝트의 src 폴더에 가져오도록 하자. 2. index.js에 코드 추가하기아래 코드를 index.js에 추가해준다.import * as serviceWorkerRegistration from './serviceWorke..
코딩만하느라 바빴던 주차였다. 생각보다 오류들도 많이 있었고... 그것들을 해결하느라 mvp로 잡았던 기능들도 미처 다 못했고... 개인적으로는 만족스럽지 못한 결과물이었기에 더욱 아쉬움이 남은 중간 발표였던 것 같다. 이번 주의 작업 회원가입 페이지 뷰 작업 메인 페이지 CRUD 기능 구현 다이어리 북마크 기능 구현 설정 페이지들 뷰 작업 트러블 슈팅 - 모달이 다이어리 하나일 땐 되고 두 개 이상 땐 안 됨 - 다이어리 전체 조회에서 다이어리의 수정/삭제를 위한 모달을 열면 버튼의 클릭이 다이어리가 하나일 땐 되지만, 두 개 이상이면 버튼 클릭 시 기능이 작동되지 않는 버그 발생 해결 과정 및 해결 (1) 다이어리의 수정/삭제를 위해 props로 넘어오는 다이어리 id를 콘솔로 찍어보면 같은 id가 ..
난 이번 주 뭘했던 걸까 고민만 한가득하다가 뭘했는지도 모르겠는 채 보낸 한 주였다. 프로젝트의 기술 스택이 여러번 번복되면서 결국 리액트 쿼리를 쓰기로 결정했다. 코드 컨벤션을 정했지만 각자의 코딩 스타일이 다르거나 지켜지지 않아 코드가 난잡해졌고, 초반부터 리팩토링을 염두에 두고 틀을 정해서 잡아놓고 가자와 하드코딩하더라도 일단 다 쓰고 가자가 중간에 여러번 바뀌며 코드의 일관성도 없어졌다. 그러다 보니 프로젝트의 스타일드 컴포넌트의 이름들이나 컴포넌트 나누는 작업 마저도 이도저도 아닌 게 되어버렸다. 어떻게 했어야 더 좋은 방법이었을까. 이런 고민들이 팀원들 모두 처음이다보니 알 도리가 없다. 어찌됐든 이번 주 발표 전에 리팩토링을 적어도 한번은 해야만 하게 된 바쁜 일정이기에 마음을 다 잡아야 한..
errors.email?.type과 errors.password 둘 다 undefined일 때는 버튼이 활성화되도록 조건을 주었다. 분명 맞게 쓴 것 같은데 자꾸 안 되어 아래처럼 해주었더니 적용되기 시작함. 논리곱을 잘못 이해하고 있었다. ~~and ~~가 아니라 왼쪽 값이 트루여야 오른쪽으로 넘어간다는 건데...
import React, { createContext, useContext } from "react"; const ModalRoot = ({ children }) => { const [open, setOpen] = useState(false); return ( {children} ); }; provider로 넘겨주면 모든 자식 컴포넌트에서 넘겨받은 값을 사용할 수 있음
토큰 등을 헤더에 실어 보내는 데엔 여러가지 방법이 있다. 리덕스 thunk를 사용할 때 1. 일반적인 방법 // axios 인스턴스 const instance = axios.create({ baseURL: process.env.REACT_APP_MY_API, }); export const __main = createAsyncThunk( "MAIN_FINALE", async (payload, thunkAPI) => { try { const { data } = await instance.get("/api/diary", { headers: { authorization: `Bearer ${localStorage.getItem("token")}`, } }) return thunkAPI.fulfillWithVal..
1. useQuery 두번째 인자로 요청하는 fetch함수에 signal을 실어서 보냄 export function useUser(): UseUser { const queryClient = useQueryClient(); const { data: user } = useQuery( queryKeys.user, ({ signal }) => getUser(user, signal), { initialData: getStoredUser, onSuccess: (received: User | null) => { if (!received) { clearStoredUser(); } else { setStoredUser(received); } }, }, ); 2.config에 signal을 추가 async function..
-태그- 내용 -css- overflow: auto; // 높이에 따라 스크롤 생김 white-space: pre-wrap; // 길이 스크롤 방지
const queryClient = useQueryClient(); const { data: user } = useQuery(queryKeys.user, () => getUser(user)); 유저 정보를 가져오려고 할 때 useQuery로 불러오려고 하면 애초에 유저가 정의되지 않았기에 못 가져옴 function updateUser(newUser: User): void { queryClient.setQueryData(queryKeys.user, newUser); } 쿼리 클라이언트(캐시)에 로그인할 때 받아온 user 값을 저장해줌 function clearUser() { queryClient.setQueryData(queryKeys.user, null); } 로그아웃 시 클라이언트(캐시)에서 유저 키..
useIsFetching() 현재 가져오기 상태인 쿼리 호출의 수를 나타내는 정수값을 반환 const isFetching = useIsFetching(); const display = isFetching ? 'inherit' : 'none'; return ( 로딩 등 이벤트 전역 관리 queryClient.getQueryCache().subscribe((e) => { console.log(e); });
const initialUrl = "https://swapi.dev/api/people/"; const fetchUrl = async (url) => { const response = await fetch(url); return response.json(); }; . . . const { data, fetchNextPage, hasNextPage, isLoading, isFetching, isError, error } = useInfiniteQuery( ["sw-people"], ({ pageParam = initialUrl }) => fetchUrl(pageParam), { getNextPageParam: (lastPage) => lastPage.next || undefined, // hasNextPa..
![](http://i1.daumcdn.net/thumb/C150x150/?fname=https://blog.kakaocdn.net/dn/AQ5f2/btrVBQaBQt8/X7J2GZXgjnTv62pISmusK1/img.png)
설치 npm install recoil 기본 1. index에 RecoilRoot import하기 const root = ReactDOM.createRoot(document.getElementById("root") as HTMLElement); root.render( ); 2. atoms.ts파일 생성 3. 데이터 설정하기 //const todos = useRecoilValue(todoState); (불러오고 싶을 때) //const setTodos = useSetRecoilState(todoState); (가공하고 싶은 때) //위의 두 개를 아래처럼 합칠 수 있음 const [todos, setTodos] = useRecoilState(todoState); selector 리덕스의 slice같은 기능..
![](http://i1.daumcdn.net/thumb/C150x150/?fname=https://blog.kakaocdn.net/dn/bziZWG/btrVIuK9vXu/MGfzK8bebtOy5tPcdYDPUK/img.png)
설치 npm i react-helmet npm i --save-dev @types/react-helmet import { Helmet } from "react-helmet"; . . . return ( 쓰고싶은 말 파비콘 설정도 가능함
![](http://i1.daumcdn.net/thumb/C150x150/?fname=https://blog.kakaocdn.net/dn/WHBuD/btrVBokTuRs/UfuCjpGbTsDTuGyBLirEp0/img.png)
설치 npm install --save react-apexcharts apexcharts //import ApexChart from "apexcharts"; 와 헷갈리지 않도록 주의 import ReactApexChart from "react-apexcharts"; 사용법 price.close) ?? [], }, ]} options={{ theme: { mode: "dark", }, . . . series => 사용하고자 하는 데이터 DEMOS의 데이터를 사용하거나 options 참조
포트폴리오에 넣을 프로젝트를 새롭게 시작했다. 기획했었던 아이템도 중간에 엎어지고 새로운 기술 스택도 도입하려다 보니 많은 것들을 하진 못했지만, 머리 터질듯 고민했었던 코드들도 있었다. 이번 주 익힌 것들 타입스크립트 (계속 공부 중) 리액트 쿼리 v4 (계속 공부 중) 라우터 v6 React Hook Form 라이브러리 달력 구현하기 (공휴일 적용) 트러블 슈팅 - React Hook Form에 유효성에 따른 css 입히기 - 라이브러리는 최대한 덜고 가고 싶었지만 React Hook Form도 한번 다뤄보자는 팀원의 말을 따르기로 함. 유효성에 따라 alert창 없이 인풋창의 테두리 색이 서서히 바뀌었으면 좋겠다는 요구를 반영하던 중, 라이브러리를 커스텀하는 데 어려움이 있었다. 해결 과정 및 해결..
![](http://i1.daumcdn.net/thumb/C150x150/?fname=https://blog.kakaocdn.net/dn/G75Zi/btrVKZD0ZcY/OngjcvpsmjJzkqJJ4kijuK/img.png)
1. 유니온 타입 사용하기 2. if문으로 처리하기 3. 널 병합 연산자 or 논리합 사용하기 3. ! 붙이기 (비추천) 확장 할당 어션셜로 값이 무조건 할당되어있다고 컴파일러에게 전달해 값이 없어도 변수를 사용할 수 있게 한다고 한다. 그러나 null이나 undefined도 분명히 해야할 때가 있기 때문에 무조건적으로 권장되는 방법은 아님. 4. 스프레드 연산자로 풀고 !붙이기 (비추천) 'IntrinsicAttributes & IGetData' 형식에 할당할 수 없습니다. 오류 5. !말고 ?붙이기 (추천) 6. 타입 변경하기 'number' 형식은 'string' 형식에 할당할 수 없습니다. 오류 등 layoutId={String(data.id)} 7. as로 타입 단언하기(비추) data의 타입을..