Follow the react project (to P57)

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:

  1. 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)
  1. 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} />

Keywords: Javascript Front-end React

Added by Xeoncross on Wed, 09 Mar 2022 19:50:51 +0200