Search code examples
javascriptreactjsjsonrecursionpath-finding

Find path of object property, recursively


I want to print path of object key, dynamically. Here is my code:

   const Tree = ({ data }) => {
     let path = "onboarding";
  
      return Object.keys(data).map((key) => {
        if (Array.isArray(data[key])) {
          path = path + "." + key;
          return (
              <Tree data={data[key]}></Tree> 
          );
        }

        if (typeof data[key] === "object") {
          path = path + "." + key;
          return (
              <Tree data={data[key]}></Tree>
          );
        } else {
          path = path + "." + key;    
          return (
            <input defaultValue={data[key]}
              style={{ fontWeight: "bold" }}
              disabled={!this.props.isEditable}/>

          );
        }
      });
    };

and its my data

  onboarding: {
    enumType: 1,
    key: "key1",
    steps: [
      {
        title: "STEP ONE",
        description: "des1",
        instructions: [
          {
            icon: "step_power",
            label: {
              text: "text1",
              color: "A11111",
              location: "top",
            },
          },
        ],
      },
      {
        title: "STEP TWO",
        description: "des2",
        instructions: [
          {
            icon: "step_power",
            label: {
              text: "text2",
              color: "A11111",
              location: "top",
            },
          },
       ],
    }

And i want to print path of key for each iteration, expected output :

  • "enumType"
  • "key"
  • "steps"
  • "steps[0]"
  • "steps[0].title"
  • . . .
  • "steps[1].instructions[0].label.location"

Solution

  • You have to pass the path along as prop, I made a codebox: https://codesandbox.io/s/old-browser-crgd9r

    Edit: adding relevant code here as comment suggested

    const Tree = ({ path, data }) => {
      // We have 3 cases: Array, Object or neither
      // If we have an array we want to cycle through the elements
      // and keep track of the index
      // If we have an object we want to cicle through the keys
      // otherwise just return the value
    
      if (Array.isArray(data)) {
        return data.map((element, index) => {
          let currentPath = `${path}[${index}]`;
          return (
            <Tree
              path={currentPath}
              data={element}
              key={currentPath}
            ></Tree>
          );
        });
      } else if (data instanceof Object) {
        return Object.keys(data).map((key) => {
          let currentPath = path !== "" ? `${path}.${key}` : key;
          return <Tree data={data[key]} path={currentPath} key={currentPath} />;
        });
      } else {
        return (
          <div>
            <label>{path}</label>
            <input defaultValue={data} style={{ fontWeight: "bold" }} />
          </div>
        );
      }
    };