bhch/react-json-form

Crashes when schema is edited or items are removed and has oneOf and array

Closed this issue · 2 comments

bhch commented

Steps to reproduce:

1. Paste the following schema in the playground:

{
    "oneOf": [
        {
            "properties": {
                "one": {
                    "type": "array",
                    "items": {"type": "string"}
                }
            }
        },
        {
            "properties": {
                "two": {
                    "type": "array",
                    "items": {"type": "string"}
                }
            }
        }
    ]
}

2. Select Option 2 in the form

3. Edit the the schema

After that, the playground will crash.

Cause:

When the schema is edited, the playground resets the UI with the new schema and the blank data. So, the value of the data is changing but the oneOf component still has cached the second option. So it tries to look for the keys of second subschema in the data new blank data which is of the first subschema.

Can be resolved by also resetting the selected option.

bhch commented

The cached subschema is only refreshed when a different subschema option is selected. It is not updated when an item is removed. The UI still wants to render an item based on the previously selected option, but the the data structure doesn't match. Hence it crashes.

bhch commented

If oneOf/anyOf is declared for array items, then this also happens when items are moved up/down.

The real issue in that case is we're using indices to create keys for the components. So, when the first item is removed, the array component re-renders but the keys stay the same. React thinks that the first component was not removed (because key hasn't changed). So it still renders the first component with new data but the original state (i.e. value of the option state variable is what the value of the first component was before removal).

Quickest and dirtiest way to fix it is to not cache the selected subschema option value and instead recalculate it on every render. Will certainly result in poorer performance.

Better option is to generate unique keys for array items. This will be tracked in #69.