rjsf-team / react-jsonschema-form

A React component for building Web forms from JSON Schema.
https://rjsf-team.github.io/react-jsonschema-form/
Apache License 2.0
14.03k stars 2.18k forks source link

Live validation / onChange errors issue #4249

Open AlimovSV opened 1 month ago

AlimovSV commented 1 month ago

Prerequisites

What theme are you using?

core

Version

5.x

Current Behavior

when schema contains if/then/else and a user's changes activates then/else subschemas, the live validation works but errors in the onChange event are not reflect the real ones

Expected Behavior

errors in the onChange event should always reflect the form state

Steps To Reproduce

Thus, open the repo https://github.com/AlimovSV/rjsf-onchange-issue and click checkbox, you will see error message in the UI but console.log in the onChange event handler displays empty array:

Next uncheck the checkbox you will see that form becomes valid but console log displays errors from the previous form state:

Environment

- OS:
- Node:
- npm:

Anything else?

No response

AlimovSV commented 1 month ago

Just another addition: when the schema is nested - all work fine.

nickgros commented 1 month ago

This reproduces in this playground link (Playground.tsx needs to be updated to log the errors onChange)

@AlimovSV What's the nested schema that seems to work for you? I see the same issue if I wrap the if & then schemas in an "allOf": [{ ... }]

Also interesting is that the text field in the same example does not have this issue

AlimovSV commented 1 month ago

@nickgros The workable schema is

{
  "type": "object",
  "properties": {
    "root": {
      "type": "object",
      "required": [
        "checkbox"
      ],
      "properties": {
        "checkbox": {
          "type": "boolean"
        }
      },
      "if": {
        "required": [
          "checkbox"
        ],
        "properties": {
          "checkbox": {
            "const": true
          }
        }
      },
      "then": {
        "required": [
          "text"
        ],
        "properties": {
          "text": {
            "type": "string"
          }
        }
      }
    }
  }
}
AlimovSV commented 2 weeks ago

I guess the problem is in this line: https://github.com/rjsf-team/react-jsonschema-form/blob/main/packages/core/src/components/Form.tsx#L617 - the form validation is proceeding with the old retrieved schema, that will be updated on the next render and we observe "delay" for one user's change. So the changes works for me:

    this.onChange = (formData, newErrorSchema, id) => {
      const { extraErrors, omitExtraData, liveOmit, noValidate, liveValidate, onChange } = this.props;
[-]   const { schemaUtils, schema, retrievedSchema } = this.state;
[+]   const { schemaUtils, schema } = this.state;
[+]   let retrievedSchema;
      if ((0, import_utils39.isObject)(formData) || Array.isArray(formData)) {
[-]     const newState = this.getStateFromProps(this.props, formData, retrievedSchema);
[+]     const newState = this.getStateFromProps(this.props, formData);
        formData = newState.formData;
[+]     retrievedSchema = newState.retrievedSchema;
      }

I'm not sure about how these changes will affect the performance, because we retrieve the schema on every form change. @nickgros thoughts?

AlimovSV commented 2 weeks ago

Also I concern about calling getStateFromProps inside the onChange. Looks like we do a validation twice, when liveValidation is on.