React-jsonschema-form: When updating the uiSchema - the form will not re-rendered

Created on 20 Mar 2017  路  22Comments  路  Source: rjsf-team/react-jsonschema-form

Prerequisites

  • [x] I have read the documentation;
  • [x] In the case of a bug report, I understand that providing a SSCCE example is tremendously useful to the maintainers.

Description

If the uiSchema is updated after the component is mounded - the render function will not be called again.
In the following case:

<Form 
    schema={this.state.schema}
    uiSchema={this.state.uiSchema}
    liveValidate
/>

When there is a change in this.state.uiSchema I would expect the component to re-render, however for some reason it doesn't happen.

Steps to Reproduce

Here is a working example:
https://jsfiddle.net/bLvk8jgy/

  1. Click on the Change uiSchema button (nothing happen)
  2. Click on the Change Schema button (the description field will be removed)

Expected behavior

I would expect the <Form> to re-render.
The uiSchema will not have the "ui:widget": "textarea" for the description so I would expect this field to change back to normal string field.

Actual behavior

Nothing happen.

Version

0.43.0

Most helpful comment

Im not sure if it's considered best practice, but I've been able to force a re-render by saving the state to a new variable, clearing the state via setState({uiSchema: {}}) and then reassigning via setState({uiSchema: <placeholder variable>})

All 22 comments

It seems to be an issue with mutating the reference to the uiSchema object stored in state; cloning just works https://jsfiddle.net/n1k0/f79q7xkd/1/

I suspect a weird issue with mutability, and it's totally unclear to me why your example works for the schema but not for the uiSchema. I don't know what to do with this issue, I'm tempted to close it but I hate not figuring out everything before doing so.

This is actually insane https://jsfiddle.net/n1k0/bLvk8jgy/1/

@n1k0 Thanks for your fast reply.
As you already noticed - something doesn't really makes sense there and I don't think this should be closed. It a bug (and a really annoying one) and I really think it should be fixed.

I think it is related to the shouldRender function the checks that values of the props/state, but I couldn't figure out the cause there.

BTW, if I try to forceUpdate the component it still doesn't work :(

I wonder if we're not hitting some React bug of some sort, as this doesn't make ANY sense. See my last jsfiddle, how on Earth would deleting an object property right from the state object reference would prevent actually updating state next?

Yeah, I checked your jsfiddle, it doesn't make sense.
Can you mark this as a bug? It might get more comments from others.

Well it works just fine with plain React, so I think that's a bug with our lib :( https://jsfiddle.net/n1k0/cfcswq0m/1/

Well - the problem is that it works with the schema and with the formData objects but not with the uiSchema one, so I guessed it's a bug with this specific lib.
Any idea why the forceUpdate() doesn't work? It might help narrow down the cause.

Look at this one, how beautiful is this? https://jsfiddle.net/bLvk8jgy/2/

We may be hitting a silly JavaScript oddity:

> a = {a: 1}
Object {a: 1}
> b = a
Object {a: 1}
> a === b
true
> delete a.a
true
> a === b
true

And in your example it works with schema as we're deleting a nested property.

I guess this should require some workaround (or code change).

That actually may be a bug in our deepEquals implementation indeed.

Note that meanwhile, destructuring a spread rest property object solves your issue:

    changeUiSchema() {
      // popping out the description property
      let {description, ...uiSchema} = this.state.uiSchema;

      this.setState({ uiSchema })
    }

Also, the React docs state that directly altering component state properties is a bad practice:

Never mutate this.state directly, as calling setState() afterwards may replace the mutation you made. Treat this.state as if it were immutable.

This will work only if I remove property from the uiSchema, however if I change a nested property in a child of the uiSchema it will not work :(

You have to ensure the new uiSchema object passed to setState doesn't share the same reference, eg. https://jsfiddle.net/f79q7xkd/4/

Well, using the following didn't work as expected:

const {...uiSchema} = this.state.uiSchema;
console.log(uiSchema == this.state.uiSchema); // false
uiSchema.description['classNames'] = 'plop'
this.setState({ uiSchema })

https://jsfiddle.net/f79q7xkd/5/

Sorry if it was unclear, that's what I tried to explain in my previous comment; you need to ensure nested object references are different, so the render check returns an accurate result.

Note that const {...uiSchema} = this.state.uiSchema; will not deeply clone an object, just its first-level properties. Yeah, I know, but it's JavaScript.

After having given a lot of thought about this, I feel like this is both a JavaScript and React issue, and I couldn't come with a simple and efficient way to circumvent this behavior when lib users manually mutate the state object -- especially when it's clearly documented as a dangerous practice in the React docs.

I'm closing for now, though feel free to reopen if you have a better plan in mind and are willing to work on provide a fix.

Just came across this. Probably not that helpful but instead of using delete, using something like omit from lodash would solve this. I can also confirm that using assign works if you'd like to dynamically change the uiSchema. With this approach, const {uiSchema} = this.state is sufficient.

Im not sure if it's considered best practice, but I've been able to force a re-render by saving the state to a new variable, clearing the state via setState({uiSchema: {}}) and then reassigning via setState({uiSchema: <placeholder variable>})

I can confirm @jamesdebolt 's solution works for me. And I had this problem with Schema (not uiSchema)

Thanks very much @jamesdebolt - your workaround is working for me too. @n1k0 thanks for working through this and figuring out the cause, it's saved me abandoning JSONSchemaForm on this project.

Was this page helpful?
0 / 5 - 0 ratings