# Dependent fields with middleware correct only for new rows

**URL:** <https://jsonforms.discourse.group/t/dependent-fields-with-middleware-correct-only-for-new-rows/2006>\
**Category:** General\
**Created:** [March 1, 2024, 4:31pm UTC](https://jsonforms.discourse.group/t/dependent-fields-with-middleware-correct-only-for-new-rows/2006 "2024-03-01T16:31:12Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![Aidan](https://avatars.discourse-cdn.com/v4/letter/a/c5a1d2/32.png) [@Aidan](https://jsonforms.discourse.group/u/Aidan)\
**Post date:** [March 1, 2024, 4:31pm UTC](https://jsonforms.discourse.group/t/dependent-fields-with-middleware-correct-only-for-new-rows/2006/1 "2024-03-01T16:31:12Z")

</div>

Hi,

I’m trying to populate a select in a second form based on the data entered in the first one. The middleware has been very helpful for this, however I’m struggling with the lifecycle.

If you populate the data in Top and then add a row in Bottom it works as expected.  
However if you add a row in Bottom and then add or edit a row in Top the options aren’t changed, even though the schema has been.

This is also the case if it’s all done in one schema.

Is there a way to trigger the selects to re-render when the schema is changed? Is there another way to approach this?

```auto
import {
  materialRenderers,
  materialCells,
} from "@jsonforms/material-renderers";
import { JsonForms } from "@jsonforms/react";

export default function ExampleForm(props) {
  const firstSchema = {
    type: "object",
    properties: {
      top: {
        type: "array",
        items: {
          type: "object",
          properties: {
            firstField: {
              type: "string",
              enum: ["foo", "bar", "baz"],
            },
            secondField: {
              type: "string",
            },
          },
        },
      },
    },
  };

  const secondSchema = {
    type: "object",
    properties: {
      bottom: {
        type: "array",
        items: {
          type: "object",
          properties: {
            thirdField: {
              type: "string",
              enum: ["None"],
            },
            fourthField: {
              type: "string",
            },
          },
        },
      },
    },
  };

  return (
    <>
      <JsonForms
        schema={firstSchema}
        renderers={materialRenderers}
        cells={materialCells}
        middleware={(state, action, reducer) => {
          if (action.type === "jsonforms/UPDATE") {
            const newState = reducer(state, action);
            secondSchema.properties.bottom.items.properties.thirdField.enum =
              newState.data.top.map(
                ({ firstField, secondField }) =>
                  `${firstField}: ${secondField}`,
              );
            return newState;
          } else {
            return reducer(state, action);
          }
        }}
      />

      <JsonForms
        schema={secondSchema}
        renderers={materialRenderers}
        cells={materialCells}
      />
    </>
  );
}

```

---

<div class="post-metadata">

**Author:** ![sdirix](https://yyz2.discourse-cdn.com/free1/user_avatar/jsonforms.discourse.group/sdirix/32/1073_2.png) [@sdirix](https://jsonforms.discourse.group/u/sdirix)\
**Post date:** [March 13, 2024, 1:15pm UTC](https://jsonforms.discourse.group/t/dependent-fields-with-middleware-correct-only-for-new-rows/2006/2 "2024-03-13T13:15:38Z")

</div>

Hi @Aidan,

There are multiple issues here:

- `secondSchema` is not in a React state, therefore whenever React rerenders, a new `secondSchema` is created which is then handed over to JSON Forms, i.e. you always get a new `secondSchema` without changes in
- Even when `secondSchema` is in a React state, you are not allowed to deeply modify it arbitrarily. Instead you will need to hand over a new object to JSON Forms which has the changes in it which you want to see. This is needed as we use `React.memo` for performance improvements, so when the same `secondSchema` root object is handed over, React will see that and abort rerendering.

So this should be adapted to something like this:

```tsx
import cloneDeep from 'lodash/cloneDeep';

const [schema, setSchema] = useState(initialSchema);
const [secondSchema, setSecondSchema] = useState(initialSecondSchema);

// [...]

<JsonForms
  middleware={
    (state, action, reducer) => {
      if (action.type === "jsonforms/UPDATE") {
        const newState = reducer(state, action);
        setSecondSchema(secondSchema => {
          const newSchema = cloneDeep(secondSchema);
          newSchema.properties.bottom.items.properties.thirdField.enum =
            newState.data.top.map( ({ firstField, secondField }) => `${firstField}: ${secondField}`);
        });
        return newState;
      } else {
        return reducer(state, action);
      }
    }
  }
/>

```

Additional comments:

- For performance improvements you should only modify the `secondSchema` if `data.top` did actually change. You can check that via the `action.path`.
- Instead of a full `cloneDeep` you could also use the more specialized `lodash/fp/set` which only recreates parent objects instead of cloning the whole schema.
