Index: mapeo por posición
Index mapea por posición, no por referencia: el nodo de cada índice es estable y lo que cambia es su contenido. Por eso el item es un accessor reactivo y el índice un número fijo. Es la elección correcta para primitivos, inputs editables y listas de tamaño estable donde la identidad no vive en el dato sino en el lugar.
El nodo es la posición, el valor es la señal
Index también se suscribe a each, pero su reconciliación es de otra naturaleza: compara longitudes y posiciones, no referencias. Para cada índice i que ya existía, no recrea nada; empuja el valor nuevo dentro del signal que representa esa fila, de modo que solo se re-ejecutan los bindings de grano fino que leen item(). Crea nodos únicamente cuando el array crece y los desecha cuando mengua. Reordenar el array bajo Index no mueve ningún nodo: la posición 0 se queda donde está y su signal simplemente recibe lo que ahora ocupe el índice 0.
import { Index, createSignal } from "solid-js";function Marcadores() { const [puntos, setPuntos] = createSignal([10, 20, 30]); return ( <ul> <Index each={puntos()}> {(punto, i) => <li>fila {i}: {punto()}</li>} </Index> </ul> );}Fíjate en los paréntesis: punto() con paréntesis porque es un accessor reactivo; i sin paréntesis porque es un número fijo que nunca cambia para esa fila. Es exactamente el espejo de For. La regla que gobierna ambos es la misma —lo reactivo es lo que puede cambiar mientras la fila permanece— y aquí lo que cambia es el valor, no el sitio.
Por posición, no por referencia
La diferencia se vuelve tangible cuando muta un solo elemento. Supón que el valor de la posición 0 pasa de 10 a 99. Bajo Index, el nodo de esa fila no se toca: su signal recibe 99 y solo el nodo de texto que lo muestra se actualiza. Bajo For, en cambio, 10 y 99 son claves distintas —los primitivos se comparan por valor—, así que la fila entera se desecha y se recrea. Un mismo cambio, dos mundos.
La lección operativa: cuando la identidad vive en la posición y no en el dato, Index conserva justo lo que For destruiría. Un input en la fila 0 mantiene su foco, su cursor y su selección mientras su valor cambia por debajo, porque el elemento del DOM es literalmente el mismo. Ese es el terreno natural de Index.
Cuándo Index es la elección correcta
El patrón común a los tres casos es la ausencia de una identidad estable en el propio dato. Cuando no hay un objeto que seguir —porque son primitivos, o porque lo que importa es “la casilla número 3”, no “la entidad X”— pedirle a For que rastree referencias es pedirle que persiga fantasmas. Index acepta ese mundo tal cual: aquí las cosas se definen por dónde están.
La reconciliación de Index, paso a paso
Index no difea referencias: compara la longitud nueva con la vieja y actúa por tramos. Para los índices que ya existían, reutiliza el nodo y escribe el valor nuevo en su signal; si el array creció, añade nodos al final; si menguó, retira los sobrantes y limpia sus owners. Nunca reordena ni mueve: la posición k es siempre el mismo elemento del DOM mientras la lista tenga al menos k+1 elementos.
const [filas, setFilas] = createSignal([10, 20, 30]);// crece: se ANADE un nodo en la posicion 3, los otros no se tocansetFilas([10, 20, 30, 40]);// cambia un valor: el nodo 0 se queda, su signal pasa de 10 a 99setFilas((f) => [99, ...f.slice(1)]);// mengua: se RETIRA el ultimo nodo y se limpia su ownersetFilas((f) => f.slice(0, 2));De aquí se deduce el perfil de coste. Index es óptimo cuando los cambios son de valor o de longitud por el extremo final, y caro cuando insertas o borras por el medio, porque desplaza el sentido de todas las posiciones siguientes: cada signal recibe un valor distinto y, en la práctica, toda la cola se actualiza. Insertar al principio bajo Index reescribe todas las filas. Ese caso pide For.
Reordenar es el mismo fenómeno visto de otro ángulo. Como los nodos están anclados, “reordenar” solo significa que cada posición recibe otro valor y todas las filas mutan a la vez. Si esas filas tenían inputs con foco o estado, el resultado desconcierta: el contenido baila entre nodos que no se movieron. Es la señal más nítida de que la colección tenía identidad de objeto y pedía For.
El escenario donde Index no tiene rival es el formulario dinámico: campos cuyos valores cambian pero cuyas posiciones son fijas.
function Formulario() { const [campos, setCampos] = createSignal(["", "", ""]); const editar = (i: number, v: string) => setCampos((c) => c.map((x, k) => (k === i ? v : x))); return ( <Index each={campos()}> {(campo, i) => ( <input value={campo()} onInput={(e) => editar(i, e.currentTarget.value)} /> )} </Index> );}// Index brilla cuando la longitud crece o mengua por el finalsetCampos((c) => [...c, ""]); // anade una fila vacia, las demas intactassetCampos((c) => c.slice(0, -1)); // quita la ultima, limpia su ownerY el reverso, insertar por el principio, es su punto débil: setCampos((c) => ["", ...c]) empuja el valor de cada posición a la siguiente, y todos los inputs con foco o texto sin guardar reciben de golpe el valor de su vecino. Si tu lista inserta por el medio con datos que el usuario está editando, esa es la señal de que necesitabas identidad de objeto y, por tanto, For.