.
├── public
│ ├── favicon.ico
│ ├── index.html
│ ├── logo192.png
│ ├── logo512.png
│ ├── manifest.json
│ └── robots.txt
├── src
│ ├── App.css
│ ├── App.test.tsx
│ ├── App.tsx
│ ├── index.css
│ ├── index.tsx
│ ├── logo.svg
│ ├── react-app-env.d.ts
│ ├── serviceWorker.ts
│ └── setupTests.ts
├── README.md
├── package.json
├── tsconfig.json
└── yarn.lock
這是 create-react-app 預設的專案結構
我們可以看到 src/
裡面基本上是沒有特別的結構
因為 create-react-app 本身並沒有提供專案的推薦結構
我們必須要自己進行規劃才行
這篇主要會分享平常我們使用的結構
由於最近發現一些更好的模式(不過還沒實戰)
所以會先暫時分享目前的版本
常見基本架構
一般來說,我們會使用以下的架構做為專案的初始化
src/
components/
pages/
images/
components 裡面主要放所有的元件實作
pages 裡面則是放頁面層級的元件
images 則是放需要引入的圖片
這邊特別將 pages 拉出來是因為我們不能讓 routing 跟 components 相依
對於任一個 components 來說,應該是可以放在任何地方的
所以只要有使用到 routing 的部分,像是 useRoute
或是 withRouter(Page)
都應該是綁定到 page 層級,而 page 層級還需要簡單到可以讓人直接了解結構
ex.
const Page = () => {
return (
<div>
<Header />
<Content>
<PageTitle />
<Carousel />
</Content>
<Footer />
</div>
)
}
以功能來分類元件
再來是 components 裡面的結構,這邊在網路上有各式各樣的說法
有使用種類來分類的:
src/
components/
buttons/
PrimaryButton.tsx
SecondaryButton.tsx
DefaultButton.tsx
cards/
PaymentCard.tsx
UserCard.tsx
ProductCard.tsx
也有使用功能來分類的:
src/
components/
payment/
PaymentCard.tsx
PaymentButton.tsx
user/
UserCard.tsx
UserProfile.tsx
經過多個專案後,我們選擇了以功能來分類元件
因為如果是以種類來分類的話,常常會有功能調整時,要去很多個資料夾找元件的情況
如果是以功能區分,不論是新增或是更新功能時都能夠更好的管理
Container/Presenter Pattern
這個模式是我們目前最常用的模式,不過也是我們最近想要調整的模式
概念是將所有資料層與展示層進行分離,讓資料與樣式分開處理
src/
components/
containers/
這個模式在大部分情況是沒問題的,不過也在近期發現這不是個很好的模式
雖然我們確實地將資料處理的部分拉出了 component
但也因為如此,我們常常會在 container 的地方修正樣式
不然的話就會變成這種空殼 container:
const Container = () => {
// handle data
return <Component />
}
因為寫這篇的同時查了很多資料,發現這個模式已經不太推薦了
所以只有很簡短地介紹,避免大家太認真看待這部分
PS. 由於 Hook 的成熟,Dan Abramov 在 2019 年後開始不建議使用,但是目前在社群上還是有各種聲音,未來看看是否能補充使用 Hook 取代 Container 抽象層的方式。
Custom Hook
由於 hook 出來後,我們可以將許多狀態與資料的管理抽離元件
於是這邊仍建議使用功能來區分 hook
src/
hooks/
payment.ts
user.ts
建議一個檔案裡面有多個 hook,例如:
# payment.ts
export const useCreditCard = () => {}
export const useATM = () => {}
但這邊要強調一件事,就是不要把所有的 hook 都放到這邊
如果 hook 只跟該 component 有關,請直接放在該 component 即可,例如:
const useForm = () => {}
const SignInForm = () => {
const { onSubmit } = useForm()
return (
<form onSubmit={onSubmit}>
<input />
<button type="submit" />
</form>
)
}
export default
完整專案架構
public/
src/
pages/
{PageName}.tsx
components/
{function}/
{ComponentName}.tsx
contexts/
{Context}.tsx
hooks/
{function}.tsx
utils/
{function}.tsx
images/
{function}/
{image_name}.{png|jpg|...}
types/
{type}.d.ts
PS. types/
後續文章會介紹到,主要是定義型別用
結語
由於主要是在強調 TS 如何撰寫 React
所以這篇的部分比較短(但非常重要!!!)
因為今天實在太忙,所以篇幅較短
希望比賽後能夠好好把這篇寫好
murmur...
才第二天就要忙到快放棄了,撐下去啊....