## Create Global Style - 전체의 Element의 Style을 적용하고 싶을 때 사용한다. - 보통 `Reset Style`이나 `Font`를 설정할 때 많이 사용한다. ```jsx import styled, { createGlobalStyle } from 'styled-components'; const GlobalStyle = createGlobalStyle` /*Reset*/ ` function App() {   return (     <>       <GlobalStyle />       <Container>         <RouterProvider router={router} />       </Container>     </>   ); ``` - padding을 a태그 안에 넣어주면서 유저 친화적으로 스타일링함 ```jsx const Coin = styled.li`   background-color: white;   color: ${props => props.theme.bgColor};   margin-bottom: 10px;   padding: 20px;   border-radius: 15px;   a {     display: flex;     align-items: center;     padding: 20px;     transition: color 0.2s ease-in;   }   &:hover {     a {       color: ${props => props.theme.accentColor};     }   } `; ``` - () => () 이런식으로 함수를 쓰면 함수를 정의하지 않고 즉시 사용 가능하다. ```jsx   useEffect(() => {     (async () => {       const response = await fetch("https://api.coinpaprika.com/v1/coins");     })();   }, []); ``` ## Link를 사용해 비하인드 씬으로 값 전달하기 ```jsx <CoinsList> {coins.map((coin) => ( <Coin key={coin.id}> <Link to={`/${coin.id}`} state={{ name: coin.name }}> <Img src={`https://cryptocurrencyliveprices.com/img/${coin.id}.png`} alt={coin.name} width="35" height="35" />{coin.name} &rarr;</Link> </Coin> ))} </CoinsList> ``` - 이렇게 전달한 state는 useLocation을 통해 얻을 수 있다. ```jsx interface RouterState {   name: string; } function Coin() {   const { coinId } = useParams<keyof Params>();   const [loading, setLoading] = useState(true);   console.log(coinId);   const location = useLocation();   const name = location.state as RouterState;   return (     <Container>       <Header>         <Title>코인 {coinId}</Title>       </Header>       {loading ? (         <Loader>Loading...</Loader>       ) : null}     </Container>   ); } ``` - 하지만 이러한 방식은 이전 페이지를 반드시 방문한 다음 이동되어야 된다. - 그래서 만약 URL를 통해 직접 이동하는 경우를 대비해 조건을 걸어주는게 좋다. ## API에서 얻은 데이터들의 Type(Interface)을 쉽게 정하는 방법 - log를 통해 데이터를 본다. - 해당 데이터를 Store as global variable를 통해 변수로 저장한다. ![[F12 Img.png]] - 해당 변수에 `Object.keys(변수이름).join()`을 통해 각 Object의 `key` 값을 한 번에 파악할 수 있다. - 해당 변수에 `Object.value(변수이름).map(v => typeof v).join()`을 통해 각 Object의 `value`의 `type`을 한 번에 파악할 수 있다. - (복사 붙여넣기, Ctrl + D로 ,마다 커서를 놓고 지우고 설정하기) ## useMatch - 현재 위치를 기준으로 지정된 경로에 대한 일치 데이터를 반환합니다. - 해당 경로가 일치하면 Object를 출력하고 아니면 Null을 가진다. matchPath() : matchPath는 URL 경로 이름에 대해 경로 패턴을 일치시키고 일치에 대한 정보를 반환합니다. ## React-Query - 참고로 최신 버전의 React Quer는 @tanstack/react-query로 마이그레이션되었으므로, 밑의 명령어를 통해 설치하면 된다. (import 구문도 수정해야함) ```shell npm install @tanstack/react-query ``` - Import 구문 ```jsx import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; ``` - React-Query에서 fetcher function은 반드시 json data의 promise를 반환해야 한다. - useQuery라는 hook이 fetcher함수를 불러오고 fetcher함수가 끝이 나면 useQuery의 isLoading의 값이 True로 바꾸고 data에 API에서 나온 값을 담는다. - 데이터를 GET 하기 위한 `useQuery` api 이며, POST, UPDATE는 `useMutaion`을 사용한다. - React-Query는 데이터를 캐시에 저장해주기 때문에 - 기존 방식 ```jsx   const [coins, setCoins] = useState<CoinInterface[]>([]);   const [loading, setLoading] = useState(true);   useEffect(() => {     (async () => {       const response = await fetch("https://api.coinpaprika.com/v1/coins");       const json = await response.json();       setCoins(json.slice(0, 100));       setLoading(false);     })();   }, []); ``` - React-Query 방식 ```jsx import { useQuery } from "@tanstack/react-query"; import { fetchCoins } from "../api"; // useQuery(Coins.tsx) const { isLoading, data } = useQuery({ queryKey: ["allCoins"], queryFn: fetchCoins }); // fetcher function(api.tsx) export async function fetchCoins() {   const response = await fetch("https://api.coinpaprika.com/v1/coins");   const json = await response.json();   return json.slice(0, 100); } ``` ## React Query devTools - React Query로부터 온 정보들을 볼 수 있다. ```shell npm install @tanstack/react-query-devtools ``` - React Query 참고 자료 - https://velog.io/@tlatjdgh3778/React-Query%EC%97%90-%EB%8C%80%ED%95%9C-%EC%A0%95%EB%A6%AC - https://menduck.tistory.com/entry/%F0%9F%9A%A8%EC%9D%91%EA%B8%89%EC%8B%A4-%EC%95%8C%EB%A6%AC%EB%AF%B8-React-query%EC%97%90%EC%84%9C-error-%EC%B2%98%EB%A6%AC - React Query랑 Axios랑 다른 점 - https://velog.io/@rsoy2918/%EB%A6%AC%EC%95%A1%ED%8A%B8-%EC%BF%BC%EB%A6%ACReact-Query%EC%99%80-axios >목적과 기능: > - axios: 주로 서버와의 데이터 통신을 위해 사용됩니다. RESTful API를 호출하고 응답 데이터를 받아오는 데 중점을 둡니다. > - 리액트 쿼리: 리액트 애플리케이션에서 데이터를 가져오고 관리하는 데 사용됩니다. 여러 종류의 데이터 요청을 지원하고, 캐싱, 상태 관리, 에러 핸들링 등 데이터 관리를 위한 다양한 기능을 제공합니다. > 데이터 관리 방식: > - axios: 데이터 요청과 응답은 Promise 기반의 방식으로 처리됩니다. 콜백을 사용하거나 async/await와 같은 비동기 패턴을 사용합니다. > - 리액트 쿼리: 데이터 요청과 상태 관리는 훅(Hook) 기반으로 처리됩니다. useQuery, useMutation, useQueryClient 등의 훅을 제공하여 데이터 요청과 상태 업데이트를 간단하게 처리할 수 있습니다. > 데이터 캐싱 및 상태 관리: > - axios: 데이터 요청과 응답은 각각 독립적으로 이루어집니다. 따라서 데이터의 캐싱과 상태 관리는 개발자가 직접 처리해야 합니다. > - 리액트 쿼리: 데이터 요청과 상태 관리를 통합적으로 처리합니다. 캐싱 기능을 제공하여 중복 요청을 효율적으로 처리하고, 상태 관리를 통해 컴포넌트의 상태를 업데이트하면 쿼리가 자동으로 다시 호출되도록 설정할 수 있습니다. - 두 라이브러리는 각각의 장점과 특징에 따라 상황에 맞게 사용하면 된다. - axios는 주로 서버와의 통신에 사용되며, 리액트 쿼리는 리액트 애플리케이션에서 데이터를 효과적으로 관리하기 위해 사용된다. 따라서 데이터 요청만을 고려한다면 axios를 사용하는 것이 일반적이지만, 리액트 애플리케이션에서 데이터를 관리하는 데 추가적인 기능이 필요하다면 리액트 쿼리를 사용하는 것이 유용할 수 있다. ## apexcharts - Date 시각화 라이브러리 - 공식 문서(https://www.apexcharts.com/) ```shell npm install --save react-apexcharts apexcharts ``` ```jsx import ApexChart from "react-apexcharts"; <ApexChart       type="line"       series={[{         name: "price",         data: data?.map((price) => price.close) as number[]       },]}       options={{         chart: {           height: 500,           width: 500,           toolbar: {             show: false,           },           background: "transparent"         },         theme: {           mode: "dark",         },         stroke: {           curve: "smooth",           width: 4,         },         grid: {           show: false,         },         yaxis: {           show: false,         },         xaxis: {           labels: {             show: false,           },           axisBorder: { show: false },           axisTicks: {             show: false,           },           type: "datetime",           categories: data?.map((price) => price.time_close) as string[],         },         fill: {           type: "gradient",           gradient: {             gradientToColors: ["#0be881"],             stops: [0, 100],           },         },         tooltip: {           y: {             formatter: (value) => `${value.toFixed(2)}`,           },         },       }}     /> ``` ## Helmet - React page의 head 제목을 바꿀 수 있다. ```shell npm i react-helmet-async ``` - App()에서 HelmetProvider로 감싸고 - 각 Component에서 helmet을 통해 불러오면 된다. ```jsx import { HelmetProvider } from 'react-helmet-async'; function App() {   return (     <>       <HelmetProvider>         <GlobalStyle />         <Container>           <RouterProvider router={router} />         </Container>       </HelmetProvider>       <ReactQueryDevtools initialIsOpen={true} />     </>   ); } ``` ```jsx import { Helmet } from "react-helmet-async"; <Helmet> <title>{state?.name ? state.name : loading ? "Loading..." : infoData?.name}</title> </Helmet> ``` - 버전 충돌 발생 ```shell --legacy-peer-deps 옵션을 사용하여 설치: npm install react-helmet-async --legacy-peer-deps ```