Spaces:
Paused
Paused
File size: 2,851 Bytes
1c72248 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
import React from 'react';
/**
* Updates a deeply nested value in an object using a string path
* @param obj The object to update
* @param value The new value to set
* @param path String path to the property (e.g. 'config.process[0].model.name_or_path')
* @returns A new object with the updated value
*/
export function setNestedValue<T, V>(obj: T, value: V, path?: string): T {
// Create a copy of the original object to maintain immutability
const result = { ...obj };
// if path is not provided, be root path
if (!path) {
path = '';
}
// Split the path into segments
const pathArray = path.split('.').flatMap(segment => {
// Handle array notation like 'process[0]'
const arrayMatch = segment.match(/^([^\[]+)(\[\d+\])+/);
if (arrayMatch) {
const propName = arrayMatch[1];
const indices = segment
.substring(propName.length)
.match(/\[(\d+)\]/g)
?.map(idx => parseInt(idx.substring(1, idx.length - 1)));
// Return property name followed by array indices
return [propName, ...(indices || [])];
}
return segment;
});
// Navigate to the target location
let current: any = result;
for (let i = 0; i < pathArray.length - 1; i++) {
const key = pathArray[i];
// If current key is a number, treat it as an array index
if (typeof key === 'number') {
if (!Array.isArray(current)) {
throw new Error(`Cannot access index ${key} of non-array`);
}
// Create a copy of the array to maintain immutability
current = [...current];
} else {
// For object properties, create a new object if it doesn't exist
if (current[key] === undefined) {
// Check if the next key is a number, if so create an array, otherwise an object
const nextKey = pathArray[i + 1];
current[key] = typeof nextKey === 'number' ? [] : {};
} else {
// Create a shallow copy to maintain immutability
current[key] = Array.isArray(current[key]) ? [...current[key]] : { ...current[key] };
}
}
// Move to the next level
current = current[key];
}
// Set the value at the final path segment
const finalKey = pathArray[pathArray.length - 1];
current[finalKey] = value;
return result;
}
/**
* Custom hook for managing a complex state object with string path updates
* @param initialState The initial state object
* @returns [state, setValue] tuple
*/
export function useNestedState<T>(initialState: T): [T, (value: any, path?: string) => void] {
const [state, setState] = React.useState<T>(initialState);
const setValue = React.useCallback((value: any, path?: string) => {
if (path === undefined) {
setState(value);
return;
}
setState(prevState => setNestedValue(prevState, value, path));
}, []);
return [state, setValue];
}
|