I tried react+ TS + AntDesign for the first time. I did a project with React + TS + AntDesign, and recorded all the pits for beginners. I had to marvel how easy React Hook was to use. It seems to take more than a few words to show up in a thumbnail, but my compulsion forces me to add a lot of tick-tock
Antdesign nested subtables to get asynchronous data
1. Preliminary program: inexpandedRowRender
In the request
// Subform section
const expandedRowRender = (record: detailParams) = > {
let {errorMsg, errorOther, errorType} = record
let data = {
projectName,
errorMsg,
errorOther,
errorType
}
getErrorListDetail(data).then((da: any) = > {
if (da.bizSuccess) {
da.dataList.forEach((v: any, index: number) = > {
v.key = index
})
setSubDataSource(da.dataList)
} else {
setError(da.msg || 'Failed to get data')
}
}).catch(err= > {
setError(err)
})
const columns = [
{
title: 'Error type'.dataIndex: 'errorType'.key: 'errorType'.className: 'column-center'.width: 200}]return <div>
{error ? (<Alert message={error} type="success" closable afterClose={()= > setError(null)} />) : null}
<Table columns={columns} dataSource={subDataSource} pagination={false} />
</div>
};
Copy the code
Existing problems
After clicking once to load a subtable, requests continue to be made, creating an endless loop
why
ExpandedRowRender is called in the Render method of the Table component. React Render calls getErrorListDetail asynchronously cause repeated calls. GetErrorListDetail -> setState -> render -> getErrorListDetail -> setState -> render
2. Optimization scheme
Write the request in onExpend and render in expandedRowRender
const onExpand = (expanded: boolean, record: detailParams) = > {
if(! expanded) {// If you keep adding key-value pairs, it will cause too much data and waste resources.
// Empty the data under the corresponding key at each merge
} else {
let {errorMsg, errorOther, errorType} = record
let data = {
projectName,
errorMsg,
errorOther,
errorType
}
getErrorListDetail(data).then((da: any) = > {
if (da.bizSuccess) {
da.dataList.forEach((v: any, index: number) = > {
v.key = index
})
setSubDataSource(da.dataList)
} else {
setError(da.msg || 'Failed to get data')
}
}).catch(err= > {
setError(err)
})
}
}
Copy the code
Existing problems
Each time you click expand to request data for the current row, you modify nested subform data for other rows
why
3. Final plan
Give each row a key: rowKey={record => record.key}
const onExpand = (expanded: boolean, record: detailParams) = > {
if(! expanded) {// If you keep adding key-value pairs, it will cause too much data and waste resources.
// Empty the data under the corresponding key at each merge
constdata = { ... subDataSourceObj, [record.key]: [] } setSubDataSourceObj(data) }else {
let {errorMsg, errorOther, errorType} = record
let data = {
projectName,
errorMsg,
errorOther,
errorType
}
getErrorListDetail(data).then((da: any) = > {
const {bizSuccess, dataList, msg} = da
if (bizSuccess) {
dataList.forEach((v: any, index: number) = > {
v.key = index
})
constdata = { ... subDataSourceObj, [record.key]: dataList } setSubDataSourceObj(data) }else {
setError(msg || 'Failed to get data')
}
}).catch(err= > {
setError(err)
})
}
}
Copy the code
SubDataSourceObj [record.key] is used to display subtables
antdesign
Date component, which defaults to English international
Chinese version is required according to project requirements
import moment from 'moment'
import 'moment/locale/zh-cn'
// Put it at the end of all introductions
moment.locale('zh-cn')
<RangePicker
// Set it to Chinese
locale={zhCN}
showTime={{ format: 'HH:mm' }}
format="YYYY-MM-DD HH:mm"
onChange={(e, value) = > {onTimeChange(value)}}
/>
Copy the code
The moment and ANTD dependencies installed with NPM will only become Chinese, so you need to install them with YARN add
Run the yarn add antd moment command. The problem is resolved
About English and Chinese
- Antdesign is also in English by default, you need to add Chinese conversion to the index.tsx file
import cn from 'antd/es/locale/zh_CN';
ReactDOM.render(
<ConfigProvider locale={cn}>
<App />
</ConfigProvider>.document.getElementById('root'));Copy the code
Path problems after the project is packaged
1. The packed static resources cannot be loaded. They are all 404
- The solution
- in
package.json
Add a line of code to:"homepage": "."
- in
2. Update 404 in the production environment
- why
- Using BroswerRouter to refresh in a production environment can be problematic
- The solution
- To switch to hashHistory
Although browserHistory does a lot more, browserHistory uses HTML5’s History API, and the browser provides an interface to modify the browser’s History. HashHistory changes the browser’s history by changing the hash after the address; The History API provides pushState() and replaceState() methods to add or replace History. Hash has no method, so there is no way to replace history. But the React-Router implements this function with polyfill, as if using sessionStorage.
Another reason is that the hash part is not sent to the server by the browser, meaning that whether #foo or #bar is requested, the service only knows that the index.html is requested and does not know the hash part’s details. The History API requires server support so that the server can retrieve request details. Another reason is that some should ignore the hash part of the URL. Remember that the hash part will be lost when the URL is shared using wechat before.
But we can use hashHistory without needing too much functionality
React Hook basics notes
State of ascension
- In React, any mutable data is supposed to have a single data source, keeping the data flow top-down in the application
- Multiple components share the same data, which needs to be promoted to the nearest parent component for management
- And bidirectional data flow
- Instead of trying to synchronize state across different components, you synthesize the data at the data source
react hook
effect hook
- Side effects that do not require clearance
UseEffect is executed after each render when it is a pure function
useEffect(() = > {})
Copy the code
- Side effects that need to be removed
// Return function, can be cleared // Clear the click event useEffect(() = > { document.addEventListener('click'.console.log(1)) return () = > { document.removeEventListener('click')}})Copy the code
Control effect execution (second parameter)
UseEffect When the second argument is an empty array, it is executed only once
useEffect(() = > {}, [])
UseEffect () {useEffect () {useEffect ();
useEffect(() = > {
console.log(like)
}, [like])
Copy the code
HOC versus the pitfalls of custom hooks
HOC: Higher Order Component
The argument is a component, and the return value is a component
Customize the hook
Multiple calls (requests, etc.) can be wrapped into a function and extracted separately
useRef
- Changing the value of ref does not cause the render of the component
const likeRef = useRef(0)
console.log(likeRef.current)
Copy the code
- Common usage — get a DOM node
useContext
A way to share values between ancestor and descendant components, and between sibling components (to avoid layer by layer in the component tree)
Rules of the hook
- Use hooks only at the top level, not in loops or nested functions
- You can only call a hook in a react function or custom hook, not a js function
Other Hook
usehooks.com/
- The useReducer is used to transfer values to components
- UseCallback is used for performance tuning