把项目克隆到本地,在根目录先执行npm install
,执行npm run dev
就行了,默认用户名和密码都是admin
。
如果要发布,先执行npm run build
,成功后会产生一个dist
目录,直接把dist
目录发布即可。
如果npm run build
报错,就是TS
编译没通过,根据控制台输出的错误提示修改即可,哈哈。
先使用vite
的react-ts
模板创建的项目:
npm create vite@latest my-react-project -- --template react-ts
再安装一些类库
- axios(网络请求)
- bootstrap(页面布局)
- i18next(多语言)
- react-router-dom(路由支持)
- @tanstack/react-query(接口数据管理)
- zustand(全局状态管理)
npm install react-router-dom@6 @tanstack/react-query zustand i18next react-i18next bootstrap axios
调整后目录结构如下:
my-react-project/
├── src/
│ ├── assets/
│ ├── components/
│ ├── hooks/
│ │ ├── useAuth.ts
│ │ ├── ...
│ ├── locales/
│ │ ├── en.json
│ │ └── zh.json
│ ├── pages/
│ │ ├── layouts/
│ │ └── ...
│ ├── services/
│ │ └── apiClient.ts
│ │ └── httpService.ts
│ │ └── ...
│ ├── i18n.ts
│ └── main.tsx
│ └── router.tsx
│ └── store.ts
├── index.html
└── package.json
└── ...
API
请求相关的文件都放在src/services
下, apiClient.ts
返回一个axios
对象,其他接口直接使用它实现后台请求。
现在的演示后台是使用https://jsonplaceholder.typicode.com/
作为dummy
数据源的,开发的时候根据实际情况修改baseURL
和token
。
httpServices
是一个REST
风格的基类,开发的时候根据后台接口的实际情况也可能需要修改。其他services
文件可以继承这个httpService
进一步简化接口请求。
//src/services/apiClient.ts
import axios from "axios";
// 创建 axios 实例
const apiClient = axios.create({
baseURL: "https://jsonplaceholder.typicode.com/",
headers: {},
});
// 请求拦截器
apiClient.interceptors.request.use(
(config) => {
const token = localStorage.getItem("token");
if (token) config.headers["token"] = token;
return config;
},
(error) => {
return Promise.reject(error);
}
);
export default apiClient;
全局共享数据,如登录状态、语言选择等使用zustand
管理,参考src/store.ts
,项目地址:https://github.com/pmndrs/zustand
。
export const useStore = create<AppState>((set) => ({
language: localStorage.getItem("token") || "en",
setLanguage: (language) => {
localStorage.setItem("language", language);
set({ language });
},
}));
接口数据,不需要全局共享的如用户列表、帖子列表等使用react-query
调用,参考src/hooks/
下面的自定义hook
。react-query
自带重试、缓存、刷新等功能,项目地址:https://github.com/TanStack/query
。
const usePost = (postId: string) => {
const queryKey: QueryKey = ["post", postId];
return useQuery<Post>({
queryKey,
queryFn: () => postService.get(postId).then((response) => response.data),
staleTime: 5 * 60 * 1000,
});
};
export default usePost;
多语言使用react-i18next
处理,配置参考src/i18n.ts
和src/main.ts
。
当前示例中,翻译写在src/locales
下,目前有提供en.json
和zh.json
两个翻译文件。
开发中根据实际需要添加或修改,增加或删除语言需要修改src/i18n.ts
。
//在组件中使用翻译
import { useTranslation } from "react-i18next";
const { t } = useTranslation();
return (
<button onClick={handleClick} className="btn btn-primary">
{t("Back")}
</button>
);
路由使用react-router-dom@6
,路由配置参考src/router.tsx
和src/main.ts
。
当前示例包含一个/login
公共路由和一组/
下的保护路由,登录后才能访问。
开发中根据实际需要修改src/router.tsx
即可。