How can I simplify this redundant React code in the component?

Viewed 94

So I have Material UI Textfields that get some data from an API and here is my code. It works perfectly but I want to simplify it, and I have no idea on how to even do it. I was thinking of using a map, but not sure how to deal with the nested z elements. Any help would be appreciated a lot!

P.S. I am a beginner.

             <div>
              <TextField value={queryCache.getQueryData('x1').y1}/>
              <TextField value={queryCache.getQueryData('x1').y2}/>
              <TextField value={queryCache.getQueryData('x1').y3.z1}/>
              <TextField value={queryCache.getQueryData('x1').y3.z2}/>
              <TextField value={queryCache.getQueryData('x1').y4}/>
              ...
            </div> 

3 Answers

Looks like queryCache.getQueryData('x1') is a "collection" of sorts, that holds several values accessible from different paths.

What you could do is define the list of those paths and iterate through them, getting the needed values:

const paths = [
  [ "y1" ], // [ "name" ]
  [ "y2" ], // [ "age" ]
  [ "y3", "z1" ], // [ "location", "country" ]
  [ "y3", "z2" ], // [ "location", "city" ]
  [ "y4" ], // [ "occupation" ]
];

function getValue(collection, path) {
  return path.reduce((subCollection, key) => subCollection[key], collection);
}

// Examples:
// getValue({ name: "John" }, [ "name" ])
// => "John"
// getValue({ location: { country: "US", city: "NYC" } }, [ "location", "city" ])
// => "NYC"
<div>
  {paths.map((path) => (
    <TextField value={getValue(queryCache.getQueryData('x1')), path} key={path.join(",")} />
  ))}
</div>

I'd also suggest a) putting queryCache.getQueryData('x1') in a variable and reuse it, rather than recalculating it each time, and b) coming up with a better key.

So with the help from @DrewReese I have managed to sort this out, and make it work. Here is the solution for future reference.

I have taken out the logic outside the return() and that helped me create non-redundant code.

const data = queryCache.getQueryData("x");
const values = [
  data.y1,
  data.y2.z1,
  data.y2.z2,
  data.y2.z3,
  data.y3,
  data.y4,
......
];

And then simply in my return statement for the JSX I have what @DrewReese suggested:

{values.map((value) => (
      <TextField value={value} />
    ))}

Note: I have changed the values to x/y/z as this is sensitive information that cannot be publicly visible.

Thank you for all the help!

This should work:

  const coordinates = [
        {
            x: x1,
            y: y1
        },
        {
            x: x2,
            y: y2
        },
        {
            x: x3,
            y: y3,
            z: z1
        },
        {
            x: x4,
            y: y3,
            z: z2
        },
        {
            x: x5,
            y: y4
        },
    ]

    coordinates.map(({x, y, z}) => (
        <TextField value={z ? queryCache.getQueryData(x)[y][z] : queryCache.getQueryData(x)[y] } />
    ))

Related