Saltar al contenido

Inspeccionar y manipular los hijos resueltos

Inspeccionar y transformar los hijos ya resueltos: convertirlos en array con toArray, filtrarlos por tipo, envolver cada uno y mutar los nodos desde un efecto.

De getter a array

resueltos.toArray() es tu punto de entrada. Devuelve un array de ResolvedJSXElement: la mezcla real de lo que hay entre las etiquetas —elementos DOM, cadenas, números, null—. No asumas que todo son elementos.

Un matiz para iterar: como children() memoiza, las referencias que devuelve toArray() son estables entre lecturas mientras los hijos no cambien. Por eso <For>, que reconcilia por identidad de referencia, empareja cada nodo consigo mismo sin recrearlo. Es lo contrario de leer props.children crudo, donde cada acceso daría nodos nuevos y <For> los trataría como elementos distintos en cada pasada.

toArray() es también el punto donde tipas: su retorno es ResolvedJSXElement[], y un filter con guarda de tipo —(n): n is HTMLElement => ...— estrecha esa unión para que TypeScript te deje tocar .style sin quejarse. Inspeccionar hijos en Solid es, en buena medida, un ejercicio de estrechar tipos sobre una colección heterogénea.

TSX
import { children, createEffect } from "solid-js";const resueltos = children(() => props.children);createEffect(() => {  const lista = resueltos.toArray();  console.log("cantidad:", lista.length);  console.log("tipos:", lista.map((n) => typeof n));});

Filtrar y contar

Como la lista es heterogénea, casi siempre querrás quedarte solo con los elementos. Un predicado con guarda de tipo lo deja limpio y tipado:

TSX
const soloElementos = () =>  resueltos.toArray().filter(    (n): n is HTMLElement => n instanceof HTMLElement,  );

A partir de ahí, filtrar por un criterio es trivial: por dataset, por atributo, por clase.

TSX
const visibles = () =>  soloElementos().filter((el) => el.dataset.oculto !== "true");

Este filtrado no es un ejercicio de estilo: es la base de los compound components que leen metadatos de sus hijos. Un Tabs puede extraer el título de cada panel buscando el.dataset.titulo sobre los elementos resueltos, en vez de exigir una prop aparte. Es más frágil que context —lo veremos en 8.4—, pero es una técnica legítima cuando los hijos son elementos planos cuya forma controlas.

Envolver cada hijo

Para decorar la estructura —envolver cada hijo en un <li>, una tarjeta, una celda— itera el array y compone nuevo JSX alrededor de cada nodo. Con <For> obtienes reconciliación por referencia y reactividad si los hijos cambian:

TSX
function Menu(props: { children: JSX.Element }) {  const items = children(() => props.children);  return (    <ul role="menu">      <For each={items.toArray()}>        {(item) => <li role="menuitem" class="item">{item}</li>}      </For>    </ul>  );}

Cada item es el nodo ya resuelto; insertarlo dentro del <li> funciona porque lo colocas en un sitio. Para listas estáticas, un map directo en el JSX es igual de válido y más escueto; reserva <For> para cuando el conjunto de hijos varíe en el tiempo.

Mutar los nodos resueltos

Como tienes nodos DOM de verdad, puedes modificarlos en el sitio. Hazlo siempre dentro de un createEffect: así corre tras el montaje, se re-aplica si los hijos cambian y participa en la limpieza de propiedad (ownership) del componente.

TSX
function ListaColor(props: { color: string; children: JSX.Element }) {  const resueltos = children(() => props.children);  createEffect(() => {    resueltos.toArray().forEach((n) => {      if (n instanceof HTMLElement) n.style.color = props.color;    });  });  return <>{resueltos()}</>;}

Al leer props.color y resueltos() dentro del efecto, este se re-ejecuta cuando cambia el color o cuando cambian los hijos, re-pintando exactamente lo necesario. Es imperativo, sí, pero acotado y reactivo. Es también el patrón canónico del ColoredList de la documentación de Solid: mutar el DOM resuelto desde un efecto que sigue las props.