목록전체 글 (293)
가수면
기존의 프로젝트에 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..
설치 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같은 기능..
설치 npm i react-helmet npm i --save-dev @types/react-helmet import { Helmet } from "react-helmet"; . . . return ( 쓰고싶은 말 파비콘 설정도 가능함
설치 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창 없이 인풋창의 테두리 색이 서서히 바뀌었으면 좋겠다는 요구를 반영하던 중, 라이브러리를 커스텀하는 데 어려움이 있었다. 해결 과정 및 해결..
1. 유니온 타입 사용하기 2. if문으로 처리하기 3. 널 병합 연산자 or 논리합 사용하기 3. ! 붙이기 (비추천) 확장 할당 어션셜로 값이 무조건 할당되어있다고 컴파일러에게 전달해 값이 없어도 변수를 사용할 수 있게 한다고 한다. 그러나 null이나 undefined도 분명히 해야할 때가 있기 때문에 무조건적으로 권장되는 방법은 아님. 4. 스프레드 연산자로 풀고 !붙이기 (비추천) 'IntrinsicAttributes & IGetData' 형식에 할당할 수 없습니다. 오류 5. !말고 ?붙이기 (추천) 6. 타입 변경하기 'number' 형식은 'string' 형식에 할당할 수 없습니다. 오류 등 layoutId={String(data.id)} 7. as로 타입 단언하기(비추) data의 타입을..
1. 콘솔창의 결과 전역 변수로 저장 2. Object.keys(temp1).join() 입력 후 복사 3. vscode에 붙여넣기 후 쉼표 선택 후 'Ctrl(Command)+D: 같은 문자열 선택' 4. Object.values(temp1).map(v => typeof v).join() 5. 3번 과정으로 정제 후 'Shift+Alt(Option)+i: 선택한 모든 문자열에 가장 우측 끝으로 포커싱'을 이용해 붙여넣기 JSON데이터를 타입스크립트 타입으로 빠르게 변환시켜주는 사이트 https://app.quicktype.io/?l=ts http://json2ts.com/ Instantly parse JSON in any language | quicktype app.quicktype.io
리액트 스타일드 컴포넌트를 활용한 예시) const GlobalStyle = createGlobalStyle` html { font-size: 62.5%; } body { font-size: 1.6rem; } `; rem은 최상위 요소(html 태그)에 지정된 font-size의 값을 기준으로 한다. html의 기본 font-size는 16px이다. 즉, 아무런 설정을 하지 않았을 때 1rem = 16px이라는 공식이 성립된다. 따라서 1rem을 10px로 맞추기 위해선 html의 기본 크기를 10px로 만들면 된다. 그러나 html의 font-size를 10px로 줄여버리게 되면 치명적인 문제가 생긴다. 바로 1rem이 10px이 됐을지 언정 16px이 기본값이었던 각 태그들의 font-size도 10..
숫자, 넘버 둘 다 사용하고 싶을 때 const [counter, setCounter] = useState(1); setCounter("안녕"); 로그인 로직에 적용 버튼이 form 밖에 있을 경우 MouseEvent import React, { useState } from "react"; const App = () => { const [value, setValue] = useState(""); const onChange = (event: React.FormEvent) => { const { value } = event.currentTarget; setValue(value); }; const onSubmit = (event: React.FormEvent) => { event.preventDefault()..
interface 객체의 모양을 확인해줌 예시 1) import Circle from "./Circle"; const App = () => { return ( ); }; export default App; import React from "react"; import styled from "styled-components"; interface ContainerProps { bgColor: string; } const Circle = ({ bgColor }: ContainerProps) => { return Circle; }; export default Circle; // const Container = styled.div도 가능 const Container = styled.div` width: 200px;..