Tengo un objeto que contiene una matriz de objetos con el siguiente formato que se almacena en un estado
const [value, setVal] = useState({ available : [], done: [] }) done es una matriz de objetos con la siguiente estructura
[{col: "test", val: ["abc","xyz"]}] Estoy escribiendo una función que toma el field y el value como parámetros de entrada. Si el campo está presente en la matriz done , entonces necesito insertarlo dentro de su matriz val correspondiente. De lo contrario, necesito crear un nuevo objeto y luego empujarlo hacia adentro. ¿Cómo puedo conseguir esto?
¿Cómo puedo configurar el estado en ambos casos? El código que probé está debajo
function update(field, value){ const filterIndex = value.done.findIndex((obj) => field === obj.col); if (filterIndex > -1) { value.done[filterIndex].val.push(value); } else { setVal({ ...value, done: [ ...value.done, { col: field, val: [value], } ] }); } }Debe usar un nombre de variable separado para el estado en lugar de value ya que la función tiene una variable local también llamada value .
Prueba como a continuación.
const [values, setVals] = useState({ available: [], done: [] }) function update(field, value) { const filterIndex = values.done.findIndex((obj) => field === obj.col); if (filterIndex > -1) { // get a copy of the previous state done values const updatedDone = [...values.done]; // update the new value in the copy of the array updatedDone[filterIndex].val.push(value); // update the state setVals((prevValue) => ({ ...prevValue, done: updatedDone })); } else { // add the new entry for the new filed with the value setVals((prevValue) => ({ ...prevValue, done: [ ...prevValue.done, { col: field, val: [value], }, ], })); } }Esta puede ser una posible solución:
Fragmento de código
const stateVal = { available : [], done: [{col: "test", val: ["abc","xyz"]}] }; const updateStateVal = (sv, field, value) => ({ ...sv, done: ( sv.done.map(ob => ob.col).includes(field) ? sv.done.map(ob => ( ob.col === field ? {...ob, val: ob.val.concat([value])} : {...ob} )) : sv.done.concat([{ col: field, val: [value] }]) ) }); console.log('existing col test: ', updateStateVal(stateVal, 'test', 'def')); console.log('non-exist col test2: ', updateStateVal(stateVal, 'test2', 'def'));Cómo utilizar
setVal(prev => ({...updateStateVal(prev, field, value)}));Explicación
El objetivo es insertar value basado en la presencia/ausencia de field en done .
El método updateStateVal toma 3 parámetros, el estado previo sv , el field y el value
Use ... operador de propagación para enumerar todos los accesorios de prev (es decir, sv ) tal como están
Ahora, anula el accesorio done .
Primero verifique si el estado anterior ya tiene un field done coincidir las col de cada elemento de la matriz.
Esto se hace usando .map() junto con .includes()
Si lo encuentra, itere a través de la matriz done .
Para el elemento de matriz donde col coincide con field , .concat la matriz val existente con value . Todos los demás elementos van como están.
Si no se encuentra, simplemente .concat una matriz de un solo elemento ( [{ col: field, val: [value]}] ) a la done existente.