728x90
반응형

https://reactrouter.com/docs/en/v6/upgrading/v5#upgrading-from-v5

 

React Router | Upgrading from v5

Declarative routing for React apps at any scale

reactrouter.com

v5에서 v6가 되면서 react router dom 모듈에서 변경된 점이 몇 개 있다.

1. <Switch> -> <Routes>

젤 먼저 Switch가 없어지고 Routes로 바뀌었다.

원래 Switch로 바깥을 둘러싸고 그 안에 Route를 사용하여서 이동하였으나, Switch 대신 Routes를 쓰면된다.

 

2. Route 변경

Route의 속성 중에서 component는 element로 바뀌었다.

 

3. 중첩 라우팅

: Router안에 Route를 넣어서 구현할 수 있다. 아래에 있는 변환과정을 통해 설명하겠다.

 

4. Outlet ->nested routes 구현할 때

: 만약 상위의 컴포넌트를 레이아웃화하고 싶을 때, Outlet을 사용한다. 

Outlet을 사용하면 {children}으로 사용하는것과 같은 효과가 난다.

 

5. useRouteMatch : 특정한 URL에 있는지의 여부를 알려준다.

react-router-dom v6에는 v5에 있는 useRouteMatch hook의 대체제로 useMatch()를 사용한다. 

https://ui.dev/react-router-nested-routes

 

The Guide to Nested Routes with React Router

In this comprehensive, up-to-date guide, you'll learn everything you need to know about creating nested routes with React Router.

ui.dev

 

v5에서 v6로 변환과정 예시

<Switch>
    <Route path={`/${coinId}/price`}>
      <Price />
    </Route>
    <Route path={`/${coinId}/chart`}>
      <Chart />
    </Route>
 </Switch>

위와 같은 코드를 v6 버젼으로 변경해보자.(3번을 자세하게 해보겠다.)

v6에서 nested routes를 구현하는 방법은 두 가지가 있다.

첫번째는 부모 route의 path 마지막에 /*를 적어 이 route의 내부에서 nested route가 render된다는 것을 표시하고 자식 route를 부모 route의 element 내부에 작성한다.

(상위 Route에 /*를 적어두면 된다. 여기서는 /:coinId/* 라고 Router.tsx에 기입하였다.)

<Routes>
    <Route path="price" element={<Price />}></Route>
    <Route path="chart" element={<Chart />}></Route>
</Routes>

두번째 방법은 Routes가 상대경로도 지원하기 때문에 path="chart"와 같이 써도 작동한다. 이 코드를 상위 컴포넌트에서 작성해주면 된다.

<Route path="/:coinId" element={<Coin />}}
    <Route path="chart" element={<Chart />} />
    <Route path="price" element={<Price />} />
</Route>
728x90
반응형
728x90
반응형

React에서 비동기를 쉽게 다루게 해주는 라이브러리이다. 데이터를 서버에서 가져오고 그 데이터를 모든 컴포넌트에서 사용 가능하게 캐싱하거나, 데이터 패칭 등을 지원한다. 

 

캐싱 : 예를들어 /user/2에 10초 전에 요청을 한 적이 있다면 그 때 불러온 데이터를 보여줄 수 있다. (이전에 loading을 해서 처리했던 부분이 더 빨리 진행되어 안보인다!)

편리한 기능 : data, isLoading, isSuccess, isError 등등을 사용할 수 있다.

  • 전역 상태를 건드리지 않고도 캐시하고 업데이트 할 수 있다.
  • React Query에 데이터를 가져올 위치와 데이터가 얼마나 필요한지 알려주면 즉시 캐싱, 백그라운드 업데이트 및 오래된 데이터를 처리한다.
  • 설치 : npm install react-query -> npm install @tanstack/react-query
    • react-query가 버전이 바뀌어서 @tanstack/react-query로 해야 오류가 나지 않는다. 사용법은 같다

 

React Query를 사용하기 위해서는 우선 사용하고자 하는 컴포넌트를  <QueryClientProvider> 컴포넌트로 감싸주고 provider를 만들어주어야 한다. client props는 필수이다.

QueryClientProvider 안에 있는 모든 것은 queryClient에 접근할 수 있다.

import {QueryClient,QueryClientProvider} from '@tanstack/react-query';
...
const queryClient = new QueryClient()

<QueryClientProvider client={queryClient}>
	<Todos />
</QueryClientProvider>
...

앱 전체에서 사용하고자하면 최상위 컴포넌트에 감싸주면 된다. 

 

react - query는 useEffect와 fetch, loading을 이용하는 많은 과정을 생략시켜 준다. 

 

react-query를 이용해서 데이터 패칭을 할 때는 useQuery hooks를 사용하면 된다.

useQuery의 첫번째 인자에는 문자열 혹은 배열값인 queryKey 값을 받게 되어있는데, 해당 queryKey 값으로 데이터를 캐싱하게 된다. 

useQuery(['post',1],...)
useQuery(['pst',2],...)

[예제]

  • isIdle 값은 enabled가 true가 될 때까지, fetch가 시작되기 전까지 true입니다.
  • idle : 쿼리 data가 하나도 없고 비었을 때. {enabled : false} 상태로 쿼리가 호출되었을 때 이 상태로 시작된다.
  • users.ts : axios를 이용해서 users.ts에서는 api를 받아온다. 여기서 data는 User의 배열 타입으로 지정해주고, interface를 통해서 형을 저장해준다.
//users.ts
import axios from 'axios';

const BASE_URL = '<https://jsonplaceholder.typicode.com>';

export interface User{
    id:number;
    name:string;
    username:string;
    email:string;
    address:Address;
    phone:string;
    website:string;
    company:Company;
}
interface Address{
    street:string;
    suite:string;
    city:string;
    zipcode:string;
    geo:Geo;
}
interface Geo{
    lat:string;
    lng:string;
}

interface Company{
    name:string;
    catchPhrase:string;
    bs:string;
}

const axiosUsers = async () =>{
    const response = await axios.get(`${BASE_URL}/users`);
    const data:User[] = response.data;
    return data;
}

export {axiosUsers};
  • Users.tsx : user에 있는 정보를 useQuery 훅을 통해서 받아온다.
// users.tsx
import {useQuery} from 'react-query';
import {axiosUsers} from '../api/users';

const Users = () => {
    const usersQuery = useQuery('users',axiosUsers);

    if(usersQuery.isLoading || usersQuery.isIdle){
        return <div>loading...</div>;
    }

    if(usersQuery.isError){
        return <div>Error...</div>;
    }

    return (
        <div>
            {usersQuery.data.map((user)=>{
                return <div key={user.id}>{user.username}</div>
            })}
        </div>
    )
}

export default Users;
  • App.tsx : React Query를 사용하기 위해서는 QueryClientProvider로 컴포넌트를 둘러싼다.
// App.tsx
import {QueryClient,QueryClientProvider} from 'react-query';
import Users from './components/Users';

const queryClient = new QueryClient();

function App() {
  return (
    <QueryClientProvider client={queryClient}>
      <Users />
    </QueryClientProvider>
  );
}

export default App;

 

+) 가지고 있는 기능

Devtools : render할 수 있는 component이고 React query에 있는 devtools를 import 해오면 캐시에 있는 query를 볼 수 있다. 

@tanstack/react-query로 바뀌면서 @tanstack/react-query-devtools를 따로 설치해야 한다.

728x90
반응형
728x90
반응형

https://reactjs.org/docs/hooks-rules.html

 

Rules of Hooks – React

A JavaScript library for building user interfaces

reactjs.org

여기 문서를 살펴보면

Only Call Hooks at the Top level

Don't call Hooks inside loops, conditions, or nested functions. Instead, always use Hooks at the top level of your React function, before any early returns. 

즉, hook은 문서의 최상단에 어떠한 값이 return 되기 전에 정의 되어야 한다. hook을 사용하기 전에 조건문으로 return 하는 코드가 있으면 에러가 발생하게 된다. 

Hook을 사용하는 코드를 return이 있는 코드 위로 올려서 실행해주면 된다. 

728x90
반응형
728x90
반응형

useState에 대해 간단한 활용법에 대해서만 배우고서는 사용하려니까 object 특정 값만 변경할때 문제가 생겼다.

도움을 받아서 해결하였다.

const [keyword, setKeyword] = useState([
    /label : 키워드 이름 select: 선택되었는지 여부/
    {key: index++, label: '랜덤', select: false},
    {key: index++, label: '자연', select: true},
    {key: index++, label: '건축', select: true},
    {key: index++, label: '예술', select: true},
    {key: index++, label: '뷰티', select: true},
    {key: index++, label: '교육', select: true},
    {key: index++, label: '테크', select: true},
  ]);
  const changeKeyword = e => {
    console.log(keyword[e.key]);
    setKeyword(prevState => ({
      ...prevState,
      [keyword[e.key].select]: true,
    }));
  };

처음에 하고 싶었던 것은 useState Hook을 이용해서 changeKeyword함수를 만들어 해당 select 값을 true로 바꾸어주고 싶었다.

 

아래는 수정 코드이다.

const [keyword, setKeyword] = useState([
    /*label : 키워드 이름 select: 선택되었는지 여부*/
    {key: index++, label: '랜덤', select: true},
    {key: index++, label: '자연', select: true},
    {key: index++, label: '건축', select: true},
    {key: index++, label: '예술', select: true},
    {key: index++, label: '뷰티', select: true},
    {key: index++, label: '교육', select: true},
    {key: index++, label: '테크', select: true},
  ]);
  /* 키워드 추가 */
  const changeKeyword = e => {
    let newKeywords = keyword.map(k => {
      if (k.key === e.key) {
        return {
          ...k,
          select: true,
        };
      } else {
        return k;
      }
    });
    setKeyword(newKeywords);
  };

자바스크립트 문법에 대해서 부족했었던것 같다.

 

위의 문법을 그래로 사용하여 키워드를 제거하는 함수도 만들어 주었다.

/* 키워드 삭제 */
  const remove = e => {
    console.log(e);
    let newKeywords = keyword.map(k => {
      if (k.label === e) {
        return {
          ...k,
          select: false,
        };
      } else {
        return k;
      }
    });
    setKeyword(newKeywords);
  };
728x90
반응형

+ Recent posts