The backend API interface is in this file, and the request path is known by the backend definition
List of fixed contents for each column (antd)
About render parameters
Later, I'll verify these three parameters myself, and I don't know the difference between text and record.
text and record are identical.
console.log(text === record) render: (text , record, index) => ( <span> <button onClick={() => this.print(text, record, index)}>See</button>
Result: If the column has no dataIndex set, no corresponding object property can be found, and the text parameter is the whole object directly
If the column has dataIndex:'name', the text is the value of the object's name property. record is the whole object
console.log(text, record)
Set rowKey='_of Table Component id'attribute
Notice the corresponding Form in label. Do not specify the name property on an Item, which acts only as a layout.
Complex control (antd)
Category Routing Component
How to complete a complex and multi-functional component, following common steps and requirements.
Static Page
Summary of knowledge:
The dataSource data is directly the requested array, and the array elements present the category information as objects.
Columumns determines which attributes of the object are displayed in the table based on the dataIndex.
The previous dialog, Modal, triggered the function with a button, and confirm() was used inside the function to quickly pop up the confirmation box. Here you use the Modal component label, where the property visible determines whether or not to display
<Card title={title} extra={extra}> <Table bordered rowKey='_id' dataSource={parent === '0' ? categorys : subCategorys} columns={this.columns} loading={loading} pagination={{ pageSize: 5, showQuickJumper: true, showSizeChanger: true }} /> <Modal title="Add Category" visible={showStatus === 1}> <AddForm /> </Modal> <Modal title="Modify Classification" visible={showStatus === 2}> <UpdateForm /> </Modal> </Card>
columns
this.columns = [ { title: 'Category name', dataIndex: 'name' }, { title: 'operation', width: 300, //Width of the column render: (category) => ( <span> <LinkButton onClick={() => this.showUpdate(category)}>Modify Classification</LinkButton> {this.state.parentId === '0' ? <LinkButton onClick={() => this.showSubCates(category)}> View subcategories</LinkButton> : null} </span> ) }];
Define control variable static
state = { categorys: [], // First-level Category List subCategorys: [], // Secondary Category List parentId: '0', // The ID of the parent class is used to query the secondary class parentName: '', // Name of parent category loading: false, // Identify if the Table is loading showStatus: 0, // Whether to show Modal, 0: Do not show 1: Add box 2: Update box }
get data
1. Get the list of categories display asynchronously based on parentId
getCategorys = async (parentId) => { const result = await reqCategorys(parentId) if (result.status === 0) { const categorys = result.data if (parentId === '0') { this.setState({categorys}) } else { this.setState({subCategorys: categorys}) } } else { message.error('Failed to get list') } }
2. Display a list of subcategories for the specified classification
showSubCates = (category) => { this.setState({ parentId: category._id, parentName: category.name }, () => { // Executed after status update to get the latest status data in callback function this.getCategorys() }) }
3. Change from Show Level 2 List to Level 1 List
transToCates = () => { // Because the class also stores data from a first-level list this.setState({ parentId: '0', parentName: '', subCategorys: [], showStatus: 0, }) }
4. Display the modified dialog box - (the input box should display the original value)
showUpdate = (category) => { // Input box to display original value, save in class this.category = category this.setState({ showStatus: 2 }) } <LinkButton onClick={() => this.showUpdate(category)}>Modify Classification</LinkButton>
5. Pass the current category information to the subcomponent so that it knows which categorization object to modify.
Get the Form information inside the subcomponent so that an update request can occur based on the form information.
<Modal title="Modify Classification" visible={showStatus === 2} onOk={this.reqUpdateCategory} onCancel={() => { this.setState({ showStatus: 0 }) // this.form.current.resetFields() }} destroyOnClose={true} > <UpdateForm categoryName={category.name} setForm={form => this.form = form} /> </Modal>
6. Send a request to add a classification (similar to modifying a classification request)
addCategory = () => { this.form.current.validateFields().then(async (values) => { this.setState({ showStatus: 0 }) const { parentId, categoryName } = values const result = await reqAddCategory(categoryName, parentId) if (result.status === 0) { //Added categories belong to the categories displayed on the current page if (parentId === this.state.parentId) { this.getCategorys() } else if (parentId === '0') { // Add a first-level classification under the second-level classification list, because returning a first-level classification by the second-level classification does not query the database this.getCategorys('0') } } }).catch((err) => { message.info('Please enter a category name') }) }
Point One:
Scenario: The parent/child categorization list of a query is controlled by the properties of the State object. But the setState function is updated asynchronously at this time. Consequence: When calling a function to query a categorized list, state.parentId or 0, (indicating query parent list)
And render(), state.paretId changes (shows child list)
Consult react documentation - setState()
Treat setState() as a request rather than a command to immediately update a component. For better perceived performance, React delays calling it and updates multiple components through a single pass. React does not guarantee that changes to the state will take effect immediately.
SetState() does not always update components immediately. It will defer updates in bulk. This allows this to be read immediately after calling setState(). State became a hidden danger. To eliminate potential hazards, use either componentDidUpdate or setState's callback function (setState(updater, callback), both of which guarantee triggering after applying the update. To set the current state based on the previous state, read the following about the parameter updater.
Point 2:
Reference Link One
Reference link two
Reference link three
Video scenario: If you do not modify the input box of the Form, the Form will initialize different values each time you click the Modify Classification button corresponding to a different classification list. If you modify the input box of the Form, click the Confirm and Cancel buttons of the Modal component, and the next time you click the Modify Category button, the Form will keep the value of the Input form that was last modified.
Method one (no):
Clear form data when clicking on the confirm or cancel button in the callback event
this.form.current.resetFields()
The first time you click on Name A to modify the classification, it will be read correctly; When you click on Name B again to modify the categorization, you still get the cache of Name A you clicked last time. When you click on Name B again - you will be delayed once
Method 2:
<Modal destroyOnClose={true} > Destroy child elements in Modal on close
Point 3:
- How to pass parameters to a callback function
Clicking the button executes the arrow function, which executes the callback function with arguments
onClick={() => this.showSubCates(category)
- How child components pass parameters to parent components
The parent component gives the child a function that passes arguments by the child component execution, but assigns this to the parent component
<UpdateForm setForm={form => this.form = form} />