useEffect monitors Form form changes through form.getFieldValue('xxx')

Scenes

In a subcomponent, the data of a table needs to be calculated depending on the value of a form element of the parent component.

There is no doubt that the first thing that comes to mind is to monitor the value of the elements in the form, use useEffectto monitor the changes of the form, and recalculate the rendering when the value changes.

Let me talk about my code structure first:

The Form form is a subcomponent, and the table component is also a subcomponent, and it is a relatively deep subcomponent (included under the tab page). If the Form subcomponent is a first-level subcomponent, then the form component is a fourth-level subcomponent.

Under this kind of multi-layer nesting, how to pass the form data to the corresponding form subcomponent?

Without a doubt, choose to use:useContext

In the top-level component, Form.useForm() define the Form instance, manage the data state , pass it through <context.Provider value={}></context.Provider>, and both the form sub-component and the form sub-component can receive it.

However, after the subcomponent monitoring code was written, an embarrassing problem was discovered: the value of the form element changed, but the useEffect of the subcomponent failed to monitor it.

// 子组件
import React, {
    
     useContext } from 'react'
import context from 'xxx/xxx'

const {
    
     form } = useContext<any>(context)

useEffect(() => {
    
    
	console.log('监听到了变化')
	// 下面是具体的逻辑
}, [form.getFiledValue('xx')])

Notice:

What confused me at the time was: when the value of a form element of the Form form component changes, although the subcomponent useEffect does not monitor the change, it can get the latest value through the onBlur event of the input box of the form subcomponent . form.getFiledValue('xx').

analyze

After all, the demand still needs to be developed downwards. If you can’t monitor it, then find a way to monitor it!

In the project, I used const [form] = Form.useForm();to create Form instances and manage the state of form data, which is also a recommended way for functional components.

By using useForm , the form will become an uncontrolled component , and there is no need to create a state through useState to maintain data.

And the ant official website also said: the difference between using this method and other methods of obtaining data:

Form will only refresh the changed Field , so as to avoid the performance problems that may be caused by a complete component refresh, so it is impossible to obtain the field value in real time form.getFieldsValuethrough .



useFormSeeing this, it is actually very clear that the form has become an uncontrolled component because it is used , and the state maintenance form.getFieldsValue() / form.setFieldsValue() data cannot be created through useState , and the form data can only be obtained and set through the ant design official document. So in this case, using useEffect can not monitor the changes of the form form.



In other words: form.getFieldValue('xxx');it is not responsive, and the value obtained by it will not trigger UI updates, that is: it is not a state.

However, some people may ask: I also used useEffect to monitor form.getFieldValue('xxx') before, and the UI can also be rendered normally. Are you wrong here?

A: That's right. I myself had this question before, and I have also encountered this kind of problem.



In actual projects, the number of re-renders of a react component is uncontrollable, especially when the code is not so standardized, so when you see the UI update, it may be linked in the new re-render It has been updated; or maybe the Form component in the project code uses both form = {form}the attribute and initialValuesthe attribute. As follows:

//
const [form] = Form.useForm();

<Form initialValues={
    
    formData} form={
    
    form} ref={
    
    formRef}> </Form>

solution

plan 1

Ant design @4.20 version introduces a new feature: Form.useWatch , which can directly obtain the value corresponding to the field in the form, which should be able to be monitored. For specific usage, please refer to the official website, and I won’t go into details here.

However, it is only supported after version 4.2. My project version is 4.12.3, which does not support this hooks for the time being, and the department leaders do not allow ant upgrades, so I did not try this way of writing.

And using this method, of course it can be monitored, but the performance is not very good, so it is not recommended to use it. Because it will trigger the re-render of the entire component , when the component is relatively large and listens to input real-time input, the performance consumption is terrible.

Scenario 2

Refuse to use Form.useForm(), use the initialValues ​​attribute, the form becomes a controllable component, with state, it can be monitored normally.

However, for my project code, the amount of changes is too large to be cost-effective.

Option 3

Use an useStateadditional definition state, when the value of the form element changes, use setState(), then pass its value through context.Provider , and listen to it in the subcomponent.

Option 4

useuseReducer

Both useReducer and useState are used to store and update state, which is equivalent to an upgraded version of useState.

When the number of types is large, it is recommended to use useReducer

Option 5

Watch component of Ant Plus 5

It is specially used to monitor the changes of form fields and update the local UI. (haven't tried it)

Summarize

In fact, the core point is just one sentence: The built-in method of Form is not responsive (that is, not a state) , and the value set or obtained by it will not trigger UI update, but can only refresh the changed field. It is also very simple to monitor it, just turn it into a state.

Guess you like

Origin blog.csdn.net/qq_41131745/article/details/129399504