【React&TypeScript學習系列】環境設定懶人安裝包,讓你能夠快速架好套件跟開發環境

這篇文章主要是紀錄一些初始化的步驟,包含了最初的安裝環境,編輯器、node、TypeScript、tailwindCSS、styledComponents,建立React專案,一些React套件Router、Redux。並不解釋這些使用的方式,主要是給學過的(我)快速搜尋想要的工具,想要學習詳細內容分別有各自的文章可以索引

環境安裝

  • vscode
  • nodeJS
  • TypeScript

參考:【TypeScript學習系列】快速安裝TypeScript開發環境,輕鬆建立第一個TS專案

安裝React

使用Create React App提供的指令,建立react檔案

npx create-react-app my-app –template typescript

檔案初始化

刪除不必要的部分

檔案

  • reportWebVitals.ts
  • setupTests.ts
  • App.test.tsx
  • logo.svg

程式碼

index.tsx

import reportWebVitals from './reportWebVitals';

reportWebVitals();

App.tsx

 import logo from './logo.svg';

<div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.tsx</code> and save to reload.
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>

App.css

全刪除

安裝tailwindCSS或styled-components

兩者擇一,看專案需求

tailwindCSS

依照官網的安裝流程

安裝指令

npm install -D tailwindcss postcss autoprefixer

npx tailwindcss init -p

tailwind.config.js

module.exports = {
  content: [
    "./src/**/*.{js,ts,jsx,tsx}",
    "./components/**/*.{js,ts,jsx,tsx}",
  ],
  theme: {
    extend: {},
  },
  plugins: [],
};

Index.css

@tailwind base;
@tailwind components;
@tailwind utilities;

VScode套件安裝

  • Tailwind CSS IntelliSense

styled-components

依照官網的安裝流程

參考:【React學習系列】學習React組件,讓你的UI分離,把HTML跟CSS都寫進JS裡

安裝指令

npm install --save styled-components @types/styled-components 

使用styled-components的檔案

import styled from "styled-components";

VScode套件安裝

  • styled-components-snippets

安裝React Router

依照官網的安裝流程

參考:【React學習系列】使用React Router套件簡單達成頁面跳轉畫面

安裝指令

npm install react-router-dom@6

Index.html

import { BrowserRouter } from "react-router-dom";

ReactDOM.render(
  <React.StrictMode>
    <BrowserRouter>
      <App />
    </BrowserRouter>
    ,
  </React.StrictMode>,
  document.getElementById("root")
);

使用方法

App.tsx

import { Routes, Route, Link } from "react-router-dom";

設定路徑程式碼

   <Routes>
        <Route path="/" element={<Home />} />
        <Route path="about" element={<About />}>
          <Route path=":Item" element={<Item />} />
       </Route>
    </Routes>

跳轉程式碼

 <Link to="/about">About</Link>

多個路徑

App.tsx

設定路徑程式碼,是在About頁面裡在插入一個分頁內容Main

路徑為 /about/main

import { Routes, Route, Link, Outlet } from "react-router-dom";

    <Route path="about" element={<About />}>
          <Route path="main" element={<Main />} />
        </Route>

父頁面顯示子頁面的位置

到父組件中,新增這個組件,可以讓子組件顯示在父組件設定的位置

<Outlet />

config用法

App.tsx

以下都是在App.tsx檔案作業

import { RouteObject,  useRoutes,} from "react-router-dom";

宣告

 let routerConfig: RouteObject[] = [
  {
    path: "/",
    element: <Home />,
  },
];

實作

const elements = useRoutes(routerConfig);

App組件使用

{elements}

安裝Json Server

依照npm網站的安裝流程

輸入指令,安裝Json Server到全域中

npm install -g json-server

建立db.json檔案,並且輸入測試程式碼

{
  "posts": [
    { "id": 1, "title": "json-server", "author": "typicode" }
  ],
  "comments": [
    { "id": 1, "body": "some comment", "postId": 1 }
  ],
  "profile": { "name": "typicode" }
}

輸入指令,即可獲得網址

  • http://localhost:3000/posts
  • http://localhost:3000/comments
  • http://localhost:3000/profile
json-server --watch db.json

※額外 到package.json的scripts中輸入程式碼,即可輸入指令npm run server就可以獲得網址

"server": "json-server --watch db.json"

安裝react-redex

依照官網的安裝流程

參考:

Redux Toolkit及Redux的安裝指令

npm install @reduxjs/toolkit

React-Redux的安裝指令

※最後報出module not found: error: can’t resolve ‘react-redux’ in的錯誤就安裝npm install react-redux

npm install @types/react-redux
npm install react-redux

Devtools的安裝指令

npm install --save-dev @redux-devtools/core

Chrome套件安裝

  • Redux Devtools

檔案建立

app/store.ts

import { configureStore } from "@reduxjs/toolkit";
// ...
import SliceReducer from "../features/counter/counterSlice";

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

// Infer the `RootState` and `AppDispatch` types from the store itself
export type RootState = ReturnType<typeof store.getState>;
// Inferred type: {posts: PostsState, comments: CommentsState, users: UsersState}
export type AppDispatch = typeof store.dispatch;

app/hooks.ts

import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux'
import type { RootState, AppDispatch } from './store'

// Use throughout your app instead of plain `useDispatch` and `useSelector`
export const useAppDispatch = () => useDispatch<AppDispatch>()
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector

features/ counter/ counterSlice.ts

import { createSlice, PayloadAction } from "@reduxjs/toolkit";
import type { RootState } from "../../app/store";

// Define a type for the slice state
interface CounterState {
  value: number;
}

// Define the initial state using that type
const initialState: CounterState = {
  value: 0,
};

export const counterSlice = createSlice({
  name: "counter",
  // `createSlice` will infer the state type from the `initialState` argument
  initialState,
  reducers: {
    increment: (state) => {
      state.value += 1;
    },
    decrement: (state) => {
      state.value -= 1;
    },
    // Use the PayloadAction type to declare the contents of `action.payload`
    incrementByAmount: (state, action: PayloadAction<number>) => {
      state.value += action.payload;
    },
  },
});

export const { increment, decrement, incrementByAmount } = counterSlice.actions;

export default counterSlice.reducer;

Index.tsx

import { Provider } from "react-redux";
import { store } from "./app/store";

<Provider store={store}>
        <App />
</Provider>

使用Hook取值、執行dispatch

取值

App.tsx

import { useAppSelector } from "./app/hook";
const select = useAppSelector((state) => {
    return state.SliceReducer;
});

執行dispatch

App.tsx

import { useAppDispatch } from "./app/hook";
import { increment } from "./features/counter/counterSlice";

  const dispatch = useAppDispatch();
  dispatch(increment());

使用中間層Middleware

App.tsx

import { Middleware } from "redux";

export const logger: Middleware = (store) => (next) => (action) => {
  console.log("dispatching", action);
  let result = next(action);
  console.log("next state", store.getState());
  return result;
};

app/store.ts

import { logger } from "../middleware/middleware";

export const store = configureStore({
  reducer: {
    SliceReducer,
  },
  middleware: (getMiddleware) => {
    return getMiddleware().concat(logger);
  },
});

export default store

app/store.ts

import { combineReducers } from "redux";
const rootReducer = combineReducers({ SliceReducer });

export const store = configureStore({
  reducer: rootReducer,
  middleware: (getMiddleware) => {
    return getMiddleware().concat(logger);
  },
});

export type RootState = ReturnType<typeof rootReducer>;

RTA Query

server/serverAPI.ts

  • 修改變數
  • reducerPath的值
  • 網址
  • export規則是endpoints的function名 = use”function名” Query
import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react";
// import { Pokemon } from "./types";
 
export const serverAPI = createApi({
  reducerPath: "serverAPI",
  baseQuery: fetchBaseQuery({
    baseUrl: "https://jsonplaceholder.typicode.com/",
  }),
  endpoints: (builder) => ({
    // getPokemonByName: builder.query<Pokemon, string>({
    //   query: (name) => `pokemon/${name}`,
    todoList: builder.query<any, string>({
      query: (id) => `todos/${id}`,
    }),
  }),
});
 
export const { useTodoListQuery } = serverAPI;

app/store.ts

import { serverAPI } from "../server/serverAPI";

const rootReducer = combineReducers({ 
  [serverAPI.reducerPath]: serverAPI.reducer,
});

export const store = configureStore({
  reducer: rootReducer,
  middleware: (getMiddleware) => {
    return getMiddleware().concat(serverAPI.middleware)
  },
});

App.tsx

  • 修改為import自訂義的hook
import {useTodoListQuery} from './server/serverAPI'

const { data, error, isLoading } = useTodoListQuery("1");
console.log("data", data);
console.log("error", error);
console.log("isLoading", isLoading);

結論

這些都是我在布魯斯的 TypeScript 入門攻略|輕鬆打造實時聊天室布魯斯的 TypeScript + React 全攻略|快速上手仿 Instagram UI這兩堂課程中學習到一些套件及環境安裝快速總結,基本的概念都已經課程中學習過,並且記錄在不同的文章中,以方便後續查找,那這也是為了讓我以後可以快速建立這些套件,所撰寫文章,才不會在各篇文章中翻找半天,真的有需要、忘記了內容才會在去翻看課程跟其他文章

能達到這樣的學習成效,我覺得布魯斯這兩堂課功不可沒,透過課程的學習,打下深厚的基礎跟印象,將來要再延伸學習就會相對容易,從零到一的過程是最難的,透過這兩堂課,則是幫我實現了這樣的過程,非常推薦學習

布魯斯的 TypeScript + React 全攻略|快速上手仿 Instagram UI布魯斯的 TypeScript 入門攻略|輕鬆打造實時聊天室

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。