Arrays en el store: índice, predicado y el patrón de listas
El store convierte cada índice de un array en una hoja direccionable: editas por posición, por lista de índices, por rango o por un predicado funcional que selecciona los elementos a tocar. Añadir, filtrar y reordenar viven en un actualizador que devuelve un array nuevo conservando identidad. Con For keyed, editar campos no remonta filas: ese es el patrón de listas de Solid.
El índice es una hoja más
Dentro de una ruta, un número es una clave: navega a esa posición del array igual que un string navega a la clave de un objeto. Editar el campo de un elemento concreto es, por tanto, alargar la ruta hasta él.
import { createStore } from "solid-js/store";const [estado, setEstado] = createStore({ tareas: [ { id: 1, texto: "leer", hecha: false }, { id: 2, texto: "escribir", hecha: false }, ],});setEstado("tareas", 0, "hecha", true); // elemento 0, campo hechasetEstado("tareas", 1, "texto", (t) => t + "!"); // actualizador en la hojaFíjate en lo que no ocurre: no reconstruyes el array, no reemplazas el objeto de la tarea, no tocas al elemento vecino. Solid escribe la hoja tareas[0].hecha y notifica solo a quien la lee. Si esa tarea es una fila renderizada, únicamente su casilla se actualiza; el resto de la lista ni se inmuta. Esta es la diferencia abismal con reemplazar el array entero: la edición de un campo es local de verdad.
Y la ruta no se detiene en el primer nivel del elemento: sigue tan hondo como haga falta, igual que en un objeto anidado. Un campo dentro de un subobjeto de un elemento de la lista es una hoja como cualquier otra.
// Numero y string se alternan en la ruta segun navegues array u objetosetEstado("tareas", 0, "meta", "prioridad", "alta");La regla mental es uniforme: en la ruta, un número significa «entra en esta posición del array» y un string significa «entra en esta clave del objeto». Alternándolos describes cualquier trayecto por el árbol, sin importar cuántas listas y cuántos objetos se crucen por el camino.
Seleccionar varios: índices, rangos y predicados
Rara vez conoces el índice exacto; conoces una condición. La ruta del store acepta, en la posición donde iría un índice, tres formas de selección múltiple que aplican el resto de la ruta a cada elemento elegido.
// Lista explicita de indicessetEstado("tareas", [0, 2, 4], "hecha", true);// Rango: desde, hasta, cada cuantosetEstado("tareas", { from: 0, to: 3 }, "hecha", true);// Predicado: la funcion decide que elementos entransetEstado("tareas", (t) => !t.hecha, "hecha", true); // marca las pendientessetEstado("tareas", (t) => t.id === 2, "texto", "revisar"); // por identidad de negocioEl predicado es la joya: recibe cada elemento y su índice, y donde devuelve verdadero, Solid aplica el resto de la ruta. Es un where declarativo incrustado en la escritura, que te libera de encontrar el índice a mano con un findIndex previo. Selecciona por la propiedad de negocio —el id, un estado, una fecha— y deja que el store recorra y edite en tu lugar, notificando solo a las filas que de verdad cambiaron.
Añadir, quitar, reordenar: cambia la forma del array
Editar campos toca hojas internas, pero cambiar la longitud o el orden cambia el array como colección, y eso vive en un actualizador que devuelve un array nuevo. Como devolver un array reemplaza la referencia —no se fusiona—, construyes el contenido completo del siguiente con las operaciones que producen copia.
setEstado("tareas", (t) => [...t, nueva]); // anadir al finalsetEstado("tareas", (t) => t.filter((x) => x.id !== 2)); // quitarsetEstado("tareas", (t) => [...t].sort(cmp)); // reordenarHay un idioma de anexado que aprovecha la ruta: escribir en el índice igual a la longitud crea la posición nueva. setEstado("tareas", estado.tareas.length, nueva) empuja sin reconstruir el array, útil cuando solo añades. Para quitar y reordenar, en cambio, el actualizador que devuelve la copia filtrada u ordenada es lo natural, porque la forma entera de la colección cambia.
El patrón de listas
Junta las piezas y emerge el patrón que Solid recomienda para toda lista editable. El array vive en un store; el render usa For, que es keyed por referencia de cada elemento; los campos se editan por índice o por predicado, sin tocar la colección; y la forma —añadir, quitar, ordenar— se cambia con un actualizador que preserva identidades.
import { For } from "solid-js";<For each={estado.tareas}> {(tarea, i) => ( <li> <input type="checkbox" checked={tarea.hecha} onChange={() => setEstado("tareas", i(), "hecha", (h) => !h)} /> {tarea.texto} </li> )}</For>El resultado es reactividad de grano fino a nivel de fila: marcar una casilla escribe una hoja y actualiza un solo nodo del DOM, sin recrear la lista ni recorrer a los hermanos. For mantiene cada fila viva mientras su elemento conserve la referencia, así que las ediciones de campo son gratis en términos de reconciliación y solo las verdaderas altas y bajas mueven nodos. Es la culminación de todo el nivel: la lista, que era la estructura más propensa a reaccionar en bloque, se vuelve el ejemplo más puro de grano fino.
Las lecturas derivadas encajan en el mismo patrón sin fricción. Un recuento de pendientes, un total, un filtrado para mostrar solo lo activo: todos se expresan como memos que leen el array del store, y como el store rastrea por hoja, ese memo solo se recalcula cuando cambia algo que de verdad lee.
import { createMemo } from "solid-js";const pendientes = createMemo(() => estado.tareas.filter((t) => !t.hecha).length);Marcar una tarea como hecha recalcula pendientes porque toca el campo que el memo observa; editar el texto de otra tarea, en cambio, lo deja intacto. La derivación hereda la granularidad del store: reacciona a la dimensión exacta del cambio, no a que «la lista cambió» en abstracto.