1.新建react+ts项目
npx create-react-app <appname> --template typescript
2.将本地新建项目push到远程仓库
新建远程仓库
打开本地项目目录,把当前目录下的已有文件全部加到刚刚新建的git仓库中
执行 git add .
提交加入的文件,并书写描述信息
git commit -m "item init"
将本地仓库与远程仓库关联起来
git remote add origin 远程仓库地址
把本地仓库的内容push到远程仓库
git push -u origin master
3.修改tsconfig.json文件
添加
"baseUrl": "./src", //配置绝对路径指向
注意:(4-6)步骤可以不做(是部分格式化配置工程化提交规范,暂时未理清楚,容易发生错误,后续补充)
4.安装格式化工具Prettier
yarn add --dev --exact prettier
创建格式化配置文件
echo {}> .prettierrc.json
新建prettierignore文件
.prettierignore
填入内容如下:
Ignore artifacts:
build
coverage
之后就可以用 yarn prettier --write . 去格式化代码了
团队协作开发时,为了提交前将代码格式进行统一自动化格式化处理
需要使用到 Pre-commit Hook
执行
npx mrm@2 lint-staged
将会在package.json文件scripts中多一行代码
prepare": "husky install"
"devDependencies": {
"husky": "^7.0.4",
"lint-staged": "^12.3.4",
"prettier": "2.5.1"
},
这里表示需要格式化的文件后缀,我们需要把ts,tsx结尾的添加上去
"lint-staged": {
"*.{js,css,md,ts,tsx}": "prettier --write"
}
将生成的.husky目录添加到git里面
5.因为本身项目创建会有eslint配置,这将会和我们的prettier配置冲突
因此需要专门为eslint进行配置
npm install --save-dev eslint-config-prettier
安装完成后在package.json修改,将prettier添加到eslint中
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest",
"prettier"
] //表示用prettier规则覆盖了eslint部分规则
},
6.配置 commitlint 规范工程--检测commit message 是否符合规范
npm install --save-dev @commitlint/config-conventional @commitlint/cli
添加commitlint.config.js文件定义规范,由于以下命令创建的文件编码格式非utf-8,提交时可能会报错。
所以推荐项目根目录手动创建commitlint.config.js文件后,复制粘贴module.exports = {extends: ['@commitlint/config-conventional']};
echo "module.exports = {extends: ['@commitlint/config-conventional']}" > commitlint.config.js
npx husky add .husky/commit-msg 'npx --no -- commitlint --edit "$1"' 就会在.husky目录下新增一个commit-msg文件
使用该命令取消校验: git commit -m "工程列表" --no-verify
7.安装json-server
npm install -g json-server 全局安装
npm install json-server -D项目中安装
再新建目录json_server_mock __表示辅助存在的目录
__json_server_mock__
该目录下创建db.json文件
里面可以填入内容如
{
"users":[]
}
修改package.json文件的scripts,添加 "json-server": "json-server __json_server_mock__/db.json --watch"
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject",
"prepare": "husky install",
"json-server": "json-server __json_server_mock__/db.json --watch --port 3001"
}
--port 指定端口号
最后执行 npm run json-server 就能启动mock服务了
8.创建.env 和.env.develop文件
在里面配置接口api请求地址 REACT_APP_API_URL = http://localhost:3001
引用时候:
const apiUrl = process.env.REACT_APP_API_URL
9.处理发请求时参数为空
fetch(`${apiUrl}/projects?name=${param.name}&personId=${param.personId}`)
在src下新建utils目录
新建index.js文件,内容如下:
export const isFalsy = (value) => value === 0 ? false: !value //将0排除后判断参数的bool值
//在一个函数里,改变传入的对象本身是不好的
export const cleanObject = (object) =>{
// Object.assign({},object)
const result = {...object}
Object.keys(result ).forEach(key=>{
const value = result [key]
if(isFalsy(value)) {
delete result[key]
}
})
return result
}
安装qs插件
npm install qs --save-dev
最终请求路径替换成:
fetch(`${apiUrl}/projects?${qs.stringify(cleanObject(param))}`)
最后建成的文件目录

使用jsonServer进行mock请求,以下写了一个小demo

db.json:
{
"users": [
{
"id": 1,
"name": "高修文"
},
{
"id": 2,
"name": "熊天成"
},
{
"id": 3,
"name": "郑华"
},
{
"id": 4,
"name": "王文静"
}
],
"projects": [
{
"id": 1,
"name": "骑手管理",
"personId": 1,
"organization": "外卖组",
"created": 1604989757139
},
{
"id": 2,
"name": "团购 APP",
"personId": 2,
"organization": "团购组",
"created": 1604989757139
},
{
"id": 3,
"name": "物料管理系统",
"personId": 2,
"organization": "物料组",
"created": 1546300800000
},
{
"id": 4,
"name": "总部管理系统",
"personId": 3,
"organization": "总部",
"created": 1604980000011
},
{
"id": 5,
"name": "送餐路线规划系统",
"personId": 4,
"organization": "外卖组",
"created": 1546900800000
}
]
}
index.jsx:
import React from "react";
import {cleanObject} from "../../utils";
import {SearchPanel} from "./search-panel";
import {List} from "./list";
import * as qs from "qs";
import {useEffect, useState} from "react";
const apiUrl = process.env.REACT_APP_API_URL
export const ProjectListScreen = () => {
const [param, setParam] = useState({
name: '',
personId: ''
})
const [users, setUsers] = useState([])
const [list, setList] = useState([])
useEffect(() => {
fetch(`${apiUrl}/projects?${qs.stringify(cleanObject(param))}`).then(async response => {
console.log(response)
if (response.ok) {
setList(await response.json())
}
})
}, [param])
useEffect(() => {
fetch(`${apiUrl}/users`).then(async response => {
console.log(response)
if (response.ok) {
setUsers(await response.json())
}
})
},[])
return <div>
<SearchPanel param={param} setParam={setParam} users={users}/>
<List list={list} users={users}/>
</div>
}
list.jsx:
import React from "react";
export const List = ({list, users}) => {
return <table className={'my-table'}>
<thead>
<tr>
<th>名称</th>
<th>负责人</th>
</tr>
</thead>
<tbody>
{
list.map(project => <tr key={project.id}>
<td>{project.name}</td>
<td>{users.find(user => user.id === project.personId)?.name || '未知'}</td>
{/*{?.name表示前面的表达式的内容为真时显示name}*/}
</tr>)
}
</tbody>
</table>
}
searh-panel.jsx
import React from "react";
import {useEffect, useState} from "react";
export const SearchPanel = ({param,setParam,users}) => {
return <form action="">
<div>
{/*{setParam(Object.assign({},param,{name:evt.target.value}))}*/}
<input type="text" value={param.name} onChange={evt => setParam({
...param,
name: evt.target.value
})
}/>
<select value={param.personId} onChange={evt => setParam({
...param,
personId: evt.target.value
})}>
<option value={''}>负责人</option>
{
users.map(user => <option value={user.id} key={user.id}>{user.name}</option>)
}
</select>
</div>
</form>
}
App.tsx:
import React from 'react';
import './App.css';
import {ProjectListScreen} from "./screens/project-list";
function App() {
return (
<div className="App">
<ProjectListScreen/>
</div>
);
}
export default App;











