SidePj -시작

2023. 12. 13. 01:02개발

개인 과제로 했던 프로젝트를 디벨롭해서

환경 세팅부터 배포까지

혼자 힘으로 이때까지 배운 것을 리마인드.

 

내부는 리액트 툴킷 및 외부는 쿼리를 중심으로 

커스텀 훅 및 리랜더링을 방지하기 위한

useRef, useEffetc ,React.memo , useCallback, useMemo

RestFul API 및 비동기 처리 

 

등등 해볼 생각. 

난항이 예상되지만 재밌으면 장땡아니겠음?

 

 

기본 환경 세팅 부터 

 

 

yarn 설치

npm install --global yarn

 

tsx 설치 

# yarn을 사용하는 경우
yarn create react-app my-app --template typescript

# npx를 사용하는 경우
npx create-react-app my-app --template typescript

 

리액트 폴더 생성

yarn create react-app SOLO-FAN

 

스타일 컴포넌트 설치

yarn add styled-components

 

라우터 설치

yarn add react-router-dom

 

리덕스 툴킷 설치

yarn add react-redux @reduxjs/toolkit

 

리액트 쿼리 설치

yarn add react-query

 

파이어베이스 설치

yarn add firebase 

 

axios 설치

yarn add axios

 

uuid 설치

yarn add react-uuid

 

json 설치

yarn add json-server

 

json 실행

yarn json-server --watch db.json --port 3001

 

 

 

//src폴더 아래에 폴더들 생성

components

hooks

pages

redux -> config//modules

shared

styles

firebase.js 파일 생성

 

//루트에

.env.local

 

절대 경로 설정

루트 //

jsconfig.json 

{
  "compilerOptions": {
    "baseUrl": "src"
  },

  "include": ["src"]
}

 

루트 //

.prettierrc 

{
  "printWidth": 120,
  "tabWidth": 2,
  "useTabs": false,
  "semi": true,
  "singleQuote": true,
  "bracketSpacing": true,
  "trailingComma": "none"
}

 

CSS 리셋 

styles폴더 GlobalStyles.js

import { createGlobalStyle } from 'styled-components';

const GlobalStyles = createGlobalStyle`
   v2.0 | 20110126
   License: none (public domain)
*/

html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
  margin: 0;
  padding: 0;
  border: 0;
  font-size: 100%;
  font: inherit;
  vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
  display: block;
}
body {
  line-height: 1;
}
ol, ul {
  list-style: none;
}
blockquote, q {
  quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
  content: '';
  content: none;
}
table {
  border-collapse: collapse;
  border-spacing: 0;
}

`;

export default GlobalStyles;

 

//리덕스 툴킷 세팅

redux -> config/moudles

툴킷 configureStore 세팅 


import { configureStore } from "@reduxjs/toolkit";



const store = configureStore({
  reducer: {  },
});

export default store;

 

툴킷 modules//Slice 세팅


import { createSlice } from "@reduxjs/toolkit";

const initialState = {
  number: 0,
};

const counterSlice = createSlice({
  name: "counter",
  initialState,
  reducers: {
    addNumber: (state, action) => {
      state.number = state.number + action.payload;
    },

    minusNumber: (state, action) => {
      state.number = state.number - action.payload;
    },
  },
});

// 액션크리에이터는 컴포넌트에서 사용하기 위해 export 하고
export const { addNumber, minusNumber } = counterSlice.actions;
// reducer 는 configStore에 등록하기 위해 export default 합니다.
export default counterSlice.reducer;

 

툴킷 index.js 세팅

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <Provider store={store}>
    <App />
  </Provider>
);

 

 

//리액트 쿼리 세팅 

 

쿼리 app 세팅

const queryClient = new QueryClient();

function App() {
  return (
 <>
 <QueryClientProvider client={QueryClient}>
 <GlobalStyles/>
 </QueryClientProvider>
 </>
  );
}

export default App;

 

쿼리 api 세팅 예시

api 폴더 Todo.js

import axios from "axios";

// 공통으로 뺐어요(물론 .env를 쓰는게 더 바람직해요)
const SERVER_URI = "http://localhost:4000";

const getTodos = async () => {
  const response = await axios.get(`${SERVER_URI}/todos`);
  return response.data;
};

const addTodo = async (newTodo) => {
  await axios.post(`${SERVER_URI}/todos`, newTodo);
};

export { getTodos, addTodo };

 

쿼리 invalidation 사용 예시 

import { addTodo } from "../../../api/todos";
import { QueryClient, useMutation } from "react-query";
...


function Input() {
...
    const queryClient = new QueryClient();
   
    const mutation = useMutation(addTodo, {
      onSuccess: () => {
        // Invalidate and refresh
        // 이렇게 하면, todos라는 이름으로 만들었던 query를
        // invalidate 할 수 있어요.
        queryClient.invalidateQueries("todos");
      },
  });
 
Mutation.mutate()

 

 

쿼리 컴포넌트 사용 예시 

const { isLoading, isError, data } = useQuery("todos", getTodos);

if (isLoading) {
  return <p>로딩중입니다....!</p>;
}

if (isError) {
  return <p>오류가 발생하였습니다...!</p>;

 

//라우트 세팅 

shared 폴더 Router.js

import React from "react";
// 1. react-router-dom을 사용하기 위해서 아래 API들을 import 합니다.
import { BrowserRouter, Route, Routes } from "react-router-dom";
import Home from "../pages/Home";

// 2. Router 라는 함수를 만들고 아래와 같이 작성합니다.
//BrowserRouter를 Router로 감싸는 이유는,
//SPA의 장점인 브라우저가 깜빡이지 않고 다른 페이지로 이동할 수 있게 만들어줍니다!
const Router = () => {
  return (
    <BrowserRouter>
      <Routes>
                        {/*
                        Routes안에 이렇게 작성합니다.
                        Route에는 react-router-dom에서 지원하는 props들이 있습니다.

                        path는 우리가 흔히 말하는 사용하고싶은 "주소"를 넣어주면 됩니다.
                        element는 해당 주소로 이동했을 때 보여주고자 하는 컴포넌트를 넣어줍니다.
                 */}
        <Route path="/" element={<Home />} />
      </Routes>
    </BrowserRouter>
  );
};

export default Router;

 

 App.js 세팅

 

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

 

react-router-dom Hooks이란?

* useNavigate

* useLocation

* Link

children 용도

 

 

크롬 extention 

Redux DevTools 도 다운 받아서 쓰면 좋음

'개발' 카테고리의 다른 글

세팅 2  (1) 2023.12.21
다시 시작.  (0) 2023.12.19
위치 기반 음악 공유 프로젝트 KPT  (0) 2023.12.11
리액트는 아래로  (1) 2023.12.07
모달은 처음인데?  (1) 2023.12.06