I need some input from people more experienced with Zustand to share their way of managing relational state. Currently we have the following:
Let's assume we have the example entities Campaign
, Elements
s and their Setting
s. The REST API returning them is in the following format:
GET <API>/campaigns/1?incl=elements,elements.settings
{
"id":1,
"name":"Welcome Campaign",
"elements":[
{
"id":5,
"type":"heading",
"label":"Heading",
"content":"Welcome!",
"settings":[
{
"id":14,
"name":"backgroundColor",
"value":"#ffffff00"
},
{
"id":15,
"name":"color",
"value":"#ffffff00"
}
]
},
{
"id":6,
"type":"button",
"label":"Button",
"content":"Submit",
"settings":[
{
"id":16,
"name":"backgroundColor",
"value":"#ffffff00"
},
{
"id":17,
"name":"color",
"value":"#ffffff00"
},
{
"id":18,
"name":"borderRadius",
"value":"3px"
}
...
]
}
...
]
}
What we are currently doing in the Reactjs app is fetching this data, then transforming it to the following normalized format and set
functions:
const useCurrentCampaignStore = create(
combine(
{
campaign: {
id: 1,
name: "Welcome Campaign"
},
elements: [
{
id: 5,
campaignId: 1,
type: "heading",
label: "Heading",
content: "Welcome!"
},
{
id: 6,
campaignId: 1,
type: "button",
label: "Button",
content: "Submit"
}
],
settings: [
{
id: 14,
elementId: 5,
name: "backgroundColor",
value: "#ffffff00"
},
{
id: 15,
elementId: 5,
name: "color",
value: "#ffffff00"
},
{
id: 16,
elementId: 6,
name: "backgroundColor",
value: "#ffffff00"
},
{
id: 17,
elementId: 6,
name: "disabled",
value: false
},
{
id: 18,
elementId: 6,
name: "borderRadius",
value: 3,
}
]
},
set => ({
updateSetting: (id: string | number, newValue: string | number | boolean) =>
set(state => {
const settings = [...state.settings];
return {
...state,
settings: settings.map(setting => {
if (setting.id == id) {
return { ...setting, value: newValue };
}
return setting;
})
};
}),
updateElementContent: (id: string | number, newValue: string) => {
set(state => {
const elements = [...state.elements];
return {
...state,
elements: elements.map(element => {
if (element.id == id) {
return { ...element, content: newValue };
}
return element;
})
};
});
}
})
)
);
I am, however, not sure this is the optimal solution, because It's rather tedious transforming all GET
requests to a normalized format and then converting them back to nested objects when you want to construct either a POST
, PUT
or PATCH
request.
So, to put it short, how do you guys design the state in your Zustand-based RESTful-API-backed React apps?