Home > OS >  Recursion in react component that generates a form
Recursion in react component that generates a form

Time:12-02

Hi there SO!

I'm currently trying to make a form that generates based on the object supplied and this seem to work at just about anything I throw at it.

That is, until I get to a nested object.


The problem:

Once I hit the if condition (typeof value === "object") I want to have a hidden input (this works).
Then I want to go into that object I just identified, and into all child objects it may contain and generate the input on same criteria as the initial run-through.

function GenericForm(props: any) {
  var object = props.object;

  return (
    <div>
      <form>
        {Object.entries(object).map(([property, value]) => {
          let type: string = "";
          if (typeof value === "string") {
            type = "text";
          } else if (typeof value === "number") {
            type = "number";
          } else if (typeof value === "boolean") {
            type = "checkbox";
          } else if (value instanceof Date) {
            type = "date";
          } else if (typeof value === "object") {
            type = "hidden";
          }

          return [
            <label property={property} htmlFor={property}>
              {property}
            </label>,
            <input
              type={type}
              id={property}
              name={property}
              defaultValue={value as string}
              onChange={(newVal) => {
                object[property] = newVal.target.value;
              }}
            />,
          ];
        })}
      </form>
    </div>
  );
}
export default GenericForm;

I'm aware that this most likely utilizes some kind of recursion and while I have tried to solve it using recursion, I haven't been able to solve it.
the code pasted here is from before I tried recursion, to have a "clean sheet" from where it went wrong for me.

EDIT 1 - added info on object structure

the object passed should be completely generic and allow for objects of any structure to be handed to the component, currently it should then just evaluate what type the properties are and make an input element from that.

one of the current objects I'm passing have the following JSON Schema

{
    "id": "XYZ1",
    "type": "twilio-api",
    "sid": "someSID",
    "from": " phonenumberhere",
    "name": "TWILIO SMS",
    "credentials": {
        "token": "someapitoken"
    }
}

above object currently renders like so:

enter image description here

CodePudding user response:

Assuming you have a Input component:

  function Input = ({ name, type, value }) => {
    // most of your code can fit here
    return <input name={name} type={type} value={value} />
  }

You can use your version of code, I use a simplified version as above to make our discussion easier. With that we can design a InputList component:

  function InputList = ({ object }) => {
    console.log('list', object)
    return (
      <div>
        {Object.entries(object).map(([property, value]) => {
           if (typeof value === "object") {
             return <InputList object={value} />
           } else {
             return <Input name={property} />
           }
        })}
      </div>
    )
  }

You can see inside this InputList, there's a call to InputList again, so that is the recursion you are looking for. The recursion stops when you don't have an object inside an object any more.

NOTE: React requires value and onChange to drive any input box. Otherwise they'll just behave like a native input. But this is not part of this question.

  • Related