I have the following
export type TRange = [number, number, string?, string?]
export const splitToken = (
token: string,
separator: string = '|',
): string[] | string => {
if (voca.includes(token, separator)) {
return voca.split(token, separator)
}
return ''
}
update(property: string, path: string, range: TRange) {
store.update(
write((state: IPreference) => {
if (splitToken(path).length === 0) {
state[path] = { ...state[path], [property]: range }
}
if (splitToken(path).length === 2) {
const path0: string = splitToken(path)[0]
const path1: string = splitToken(path)[1]
state[path0][path1] = { ...state[path0][path1], [property]: range }
}
if (splitToken(path).length === 3) {
const path0: string = splitToken(path)[0]
const path1: string = splitToken(path)[1]
const path2: string = splitToken(path)[2]
state[path0][path1][path2] = {
...state[path0][path1][path2],
[property]: range,
}
}
}),
)
}
I am looking for a better way to generate the final path in the write() function above eg
state[path0][path1][path2][..n]
The above works but it just does not scales very well.
CodePudding user response:
I would suggest to follow this path:
update(property: string, path: string, range: TRange) {
const steps = splitToken(path);
// We leave this case as it was originally in your code
if (!steps.length) {
state[path] = { ...state[path], [property]: range };
return;
}
// We split the steps to achieve the branch of the object you need, leaving the last one aside.
const addressSteps = steps.slice(0, -1);
const lastStep = addressSteps[addressSteps.length - 1];
// We get to the branch you need to update
const stateBranch = addressSteps.reduce((final, step) => final[step], state);
stateBranch[lastStep] = {...stateBranch[lastStep], [property]: range};
}
CodePudding user response:
Another example using a plain old for loop to update the original object.
function update(state: any, path: string, value: any): any {
const parts = path.split('|');
setState(state, parts, value);
}
function setState(state: any, parts: string[], value: any) {
let statePointer = state;
for (let i = 0; i < parts.length - 1; i = 1) {
if (typeof statePointer[parts[i]] !== 'object') {
statePointer[parts[i]] = {}; // sets or overwrites any other value than 'object'
// ... or throw exception depending on your requirements
}
statePointer = statePointer[parts[i]];
}
statePointer[parts[parts.length-1]] = value;
}
const preferences = {
'foo': {
'bar': true,
}
}
update(preferences, 'foo|bazz|password', 'hunter2');
console.log(JSON.stringify(preferences, null, 2));
Output:
{
"foo": {
"bar": true,
"bazz": {
"password": "hunter2"
}
}
}