Tengo una lista de dos selecciones desde donde puedo seleccionar el valor
lista uno = "A", "B"
lista dos = "C", "D", "E", "F"
Tengo un estado en react const [filterTags, setFilterTags] = useState({ one: [], two: [] });
Puedo pasar un valor a la vez desde cualquiera de la lista en updateValue(val) Necesito actualizar las etiquetas de filtro de tal manera que si su val es de la lista one que es A o B debería actualizar el estado como este {one:["A"]: two:[]}
const updateValue = (val) => { if (val === 'A' || val === 'B') { setFilterTags({ one: val }); } else { setFilterTags({ ...filterTags, two: val }); } }; si paso ACCDBAEC uno por uno, debería actualizar la matriz con los valores únicos y la salida debería ser
{one:["A"]: two:[]} //passing A {one:["A"]: two:["C"]} //passing C {one:["A"]: two:["C"]} // same since C is already there in two on passing C {one:["A"]: two:["C","D"]} //passing D {one:["A","B"]: two:["C","D"]} //passing B {one:["A","B"]: two:["C","D"]} //same since A is already present in one on //passing A {one:["A","B"]: two:["C","D","E"]} //passing E {one:["A","B"]: two:["C","D","E"]}// final output on passing Cdebería actualizar el elemento respectivo con valores únicos en este momento, el código anterior solo puede actualizar un valor único
Debe asegurarse de que solo está agregando elementos que aún no están allí, puede usar la función de includes en las matrices para verificar eso, y también quiere asegurarse de mantener todo el contenido anterior.
Una posible solución podría ser hacer lo siguiente:
const updateValue = (val) => { if (val === 'A' || val === 'B') { if(!filterTags.one.includes(val)) { setFilterTags((prev) => ({ one: [...prev.one, val], two: prev.two })); } } else { if(!filterTags.two.includes(val)) { setFilterTags((prev) => ({ one: prev.one, two: [...prev.two, val] })); } } };Este código comentado puede ayudarte:
const updateValue = (val) => { //creating a temporary copy of filterTags const tempFilterTags = {...filterTags} //checking if val is A or B and if finterTag.one does not contain the value if ((val === 'A' || val === 'B') && filterTags.one.find(el=> el == val) === null) { //if success, push the value for field one and update filterTag tempFilterTags.one.push(val) setFilterTags(tempFilterTags) } //checking if val is C, D, E of F and if finterTag.two does not contain the value if ((val === 'C' || val === 'D' || val === 'E' || val === 'F') && filterTags.two.find(el=> el == val) === null) { //if success, push the value for field two and update filterTag tempFilterTags.two.push(val) setFilterTags(tempFilterTags) } };Use la opción de actualizaciones funcionales , al configurar el estado, para obtener el valor anterior ( prev ), y use la extensión para crear un nuevo estado con los valores anteriores y actualizados. Use un Conjunto para mantener valores únicos.
const updateValue = (val) => { if (val === 'A' || val === 'B') { setFilterTags(prev => ({ ...prev, one: [...new Set([...prev.one, val])] })); } else { setFilterTags(prev => ({ ...prev, two: [...new Set([...prev.two, val])] })); } };Cómo hay demasiada repetición de código aquí, ya que la lógica para establecer el estado es idéntica y solo cambia la clave, por lo que puede refactorizarlo:
const updateValue = (val) => { const key = val === 'A' || val === 'B' ? 'one' : 'two'; setFilterTags(prev => ({ ...prev, [key]: [...new Set([...prev[key], val])] })); }; También puede usar Array.includes como lo sugiere Houssam para evitar actualizar el estado:
const updateValue = (val) => { const key = val === 'A' || val === 'B' ? 'one' : 'two'; setFilterTags(prev => { const key = val === 'A' || val === 'B' ? 'one' : 'two'; return prev[key].includes(val) ? prev : { ...prev, [key]: [...prev[key], val] }; }); };