Skip to content

Commit e5ff98b

Browse files
Merge branch 'main' into feat/migrating-to-v2-guide
2 parents c5d333d + 7827966 commit e5ff98b

File tree

1 file changed

+86
-45
lines changed

1 file changed

+86
-45
lines changed
Lines changed: 86 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,79 +1,120 @@
11
---
22
title: children
33
use_cases: >-
4-
complex children manipulation, reusing children, avoiding duplicate dom,
5-
children transformation, conditional children rendering
4+
resolving component children, normalizing JSX children, slot-like helpers,
5+
interacting with child content in library components
66
tags:
7-
- children
8-
- props
97
- components
8+
- children
109
- jsx
11-
- composition
12-
- helpers
13-
version: '1.0'
10+
- utilities
11+
version: "1.0"
1412
description: >-
15-
Use the children helper for complex child manipulation in Solid.js. Resolve,
16-
reuse, and transform component children without creating duplicate DOM.
13+
Resolve and normalize a component's `children` prop into a stable accessor.
14+
Useful when you need to read or transform children imperatively inside a
15+
component.
1716
---
1817

19-
```tsx
20-
import { children } from "solid-js";
21-
import type { JSX, ResolvedChildren } from "solid-js";
18+
`children` normalizes a component's `children` prop into a stable accessor that returns resolved JSX elements.
19+
It accepts functions, arrays, fragments, and nested structures.
2220

23-
function children(fn: () => JSX.Element): () => ResolvedChildren
21+
## Import
2422

23+
```ts
24+
import { children } from "solid-js";
2525
```
2626

27-
The `children` helper is used for more complex interactions with props.
28-
When you're not just passing children to another component using `props.children` once in JSX, you should use `children`.
29-
Props are normally passed in via a getter for `props.children` in this manner:
27+
## Type
3028

31-
```tsx
32-
const resolved = children(() => props.children)
29+
```ts
30+
function children(fn: Accessor<JSX.Element>): ChildrenReturn;
31+
32+
type ChildrenReturn = Accessor<ResolvedChildren> & {
33+
toArray: () => ResolvedChildren[];
34+
};
3335
```
3436

35-
The return value is a [memo](/reference/basic-reactivity/create-memo) evaluating to the resolved children, which updates whenever the children change.
36-
Using this memo instead of accessing `props.children` directly has some important advantages in some scenarios.
37-
The underlying issue is that, when you specify component children via JSX, Solid automatically defines `props.children` as a property getter, so that the children are created (in particular, DOM is created) whenever `props.children` gets accessed.
37+
## Parameters
38+
39+
### `fn`
40+
41+
- **Type:** `() => JSX.Element`
42+
- **Required:** Yes
43+
44+
An accessor that returns the `children` value (typically `props.children`).
45+
46+
## Return value
3847

39-
Two particular consequences:
48+
- **Type:** `ChildrenReturn`
4049

41-
1. If you access `props.children` multiple times, the children (and associated DOM) get created multiple times.
42-
This is useful if you want the DOM to be duplicated (as DOM nodes can appear in only one parent element), but in many cases it creates redundant DOM nodes.
43-
If you instead call `resolved()` multiple times, you re-use the same children.
50+
The function returns a callable accessor.
51+
Calling it yields the resolved children, either a single element or an array.
4452

45-
2. If you access `props.children` outside of a tracking scope (e.g., in an event handler), then you create children that will never be cleaned up.
46-
If you instead call `resolved()`, you re-use the already resolved children.
47-
You also guarantee that the children are tracked in the current component, as opposed to another tracking scope such as another component.
53+
## Helpers
4854

49-
In addition, the `children` helper "resolves" children by calling argumentless functions and flattening arrays of arrays into an array.
50-
For example, a child specified with JSX like `{count() * 2}` gets wrapped into a getter function `() => count() * 2` in `props.children`, but gets evaluated to an actual number in resolved, properly depending on a count signal.
55+
### `toArray()`
5156

52-
If the given `props.children` is not an array (which occurs when the JSX tag has a single child), then the `children` helper will not normalize it into an array.
53-
This is useful behavior e.g. when the intention is to pass a single function as a child, which can be detected via `typeof resolved() === 'function'`.
54-
If you want to normalize to an array, the returned memo has a `toArray` method _(new in 1.5)_.
57+
- **Type:** `() => ResolvedChildren[]`
5558

56-
In most cases, you don't need (and in some cases, don't want) to use the `children` helper if you're just passing `props.children` on to another component or element via JSX:
59+
- **Description:** Returns a flattened array of resolved child elements.
60+
61+
This method is exposed on the returned accessor and is useful for iteration or index-based logic.
62+
63+
## Examples
64+
65+
### Basic usage
5766

5867
```tsx
59-
const Wrapper = (props) => {
60-
return <div>{props.children}</div>
68+
function Wrapper(props) {
69+
const resolved = children(() => props.children);
70+
71+
return <div>{resolved()}</div>;
6172
}
73+
74+
// Usage
75+
<Wrapper>
76+
<span>one</span>
77+
<span>two</span>
78+
</Wrapper>;
6279
```
6380

64-
An important aspect of the `children` helper is that it forces the children to be created and resolved, as it accesses `props.children` immediately.
65-
This can be undesirable for conditional rendering, e.g., when using the children within a [`<Show>`](/reference/components/show) component.
66-
For example, the following code always evaluates the children:
81+
### `.toArray()` example
6782

6883
```tsx
69-
const resolved = children(() => props.children)
84+
function List(props) {
85+
const resolved = children(() => props.children);
86+
const items = resolved.toArray();
87+
88+
return (
89+
<ul>
90+
{items.map((child) => (
91+
<li>{child}</li>
92+
))}
93+
</ul>
94+
);
95+
}
7096

71-
return <Show when={visible()}>{resolved()}</Show>
97+
// Usage
98+
<List>
99+
<span>one</span>
100+
<span>two</span>
101+
</List>;
72102
```
73103

74-
To evaluate the children only when `<Show>` would render them, you can push the call to children inside a component or a function within `<Show>`, which only evaluates its children when `when` condition is true.
75-
Another nice workaround is to pass `props.children` to the children helper only when you actually want to evaluate the children:
104+
> [!NOTE]
105+
> `children` resolves the current value of `props.children`.
106+
> If `props.children` is reactive, the resolved accessor reflects updates.
107+
108+
### Working with function-as-children
109+
110+
If `children` is a function, the helper evaluates it and returns its rendered result.
76111

77112
```tsx
78-
const resolved = children(() => visible() && props.children)
79-
```
113+
function Slot(props) {
114+
const resolved = children(() => props.children);
115+
return <div>{resolved()}</div>;
116+
}
117+
118+
// Usage
119+
<Slot>{() => <span>dynamic</span>}</Slot>;
120+
```

0 commit comments

Comments
 (0)