Reputation: 93
I need suggestions on improving a UI component that receives an object that contains all data types i.e. string, int, boolean, arrays and object and displays all the data types. example of the object. PS: this object is also provide in the codesandbox link.
const data = {
foo1: {},
foo9: true,
foo3: "some random string",
foo4: "some random string",
created_at: {
$date: 1637368143.618
},
sources: {
foo1: {
first_date: {
$date: 1637368143.618
}
}
},
download: {
status: "pending"
},
foo8: "some random string",
foo5: "some random string",
foo7: ["sms"],
foo10: "some random string",
foo11: {
bar5: 0,
bar3: null,
bar1: null,
bar2: 0
},
foo28: ["some random string", "some random string2"],
foo19: "some random string"
};
currently i loop through the object and display the data in a card.
Object.entries(objSorted).map(([key, value])
but first the object is sorted to the info in the following order of string, int or boolean, array and object.
this is the link to the codesandbox. here
PS: This is more of a suggestion giving than a question, i don't have any problem with the code. i only want to know if the way am currently displaying this data is good and user friendly(i don't think so that's why i am asking). and if you think there is a better way you can comment or edit the codesandbox or create a new codesandbox.
Upvotes: 2
Views: 66
Reputation: 2097
Your intuition is correct! We can make this a little easier to understand by decomposing everything in a way similar to what you mentioned. What we really want is better separation of concerns. All of this hand waves details away, but the concepts will be what you take with you.
Step 1/2. You have data. Why not digest this before rendering? There are tons of ways of doing this, but for the sake of readability lets create a hook and be conscience about our downstream consumers. We can make our ObjectExtract component way simpler if it has well formatted data... And we can memo the results so that our digested data is cached and therefor doesn't recompute ever render.
const useCardData = (data) => {
return useMemo(() => {
const entries = Object.entries(data)
.map(([key, value]) => {
let type = "unknown";
if (Array.isArray(key)) {
type = "array";
} else if (typeof value === "boolean") {
type = "boolean";
} else if { ... };
return { type, value, key, priority: getTypeSortId(type) };
})
.sort((x, y) => x.priority - y.priority)
return entries;
}, [data]);
};
We digest our data as much as we can. The key
is needed later because using index as a key is almost never what you want since when the order changes, react uses keys to track how rows should be shifted. Numeric indexes from arrays really don't describe the uniqueness of the record. Imagine sorting the records, index 1 could mean completely different things before and after sort, and your data may or may not show up correctly. We use the object property name as our unique key, since objects do a good job of not allowing duplicate keys.
Step 3. Let's use the hook and render the data.
const CardRenderer = ({ data }) => {
const cards = useCardData(data);
return (
<>
{cards.map((thing) => {
switch (thing.type) {
case "boolean":
return <BooleanCard key={thing.key} data={thing} />;
case "string":
return <StringCard key={thing.key} data={thing} />;
case "...":
return ...;
}
}}
</>
)
};
Since our data is well formed we can simply loop over it with a switch. Instead of defining all cases and their results in one component, notice how we just create smaller card components to handle each specific case. Separation of concern. The boolean card cares about what booleans look like ect. This makes it SUPER easy to test since you can test each card individually and then test the output of our CardRenderer to make sure its output is reasonable.
Step 4. profit. We broke everything down to components
. Each piece only cares about a specific responsibility and that makes it easy to glue things together. It makes it composable. We can test each piece by itself and make sure its doing the right thing. We can make some really complex things like this while keeping the complexity of each individual hidden away.
What I described is SOLID. The examples in the link are in PHP but I think you'll get the gist. We can and should use the same patterns in react to build really cool things while managing the every growing complexity of cooler things.
Upvotes: 2