[英]How to iterate over solid-js children with typescript annotations
假设我有以下组件,我将如何遍历并渲染每个孩子来做一些事情,比如用其他组件包装每个孩子?
interface StuffProps {
children: `?`
}
function Stuff({ children }: StuffProps) {
// ?
}
我尝试设置children: JSX.Element
然后执行<For each={children}>... </For>
但它给了我一个 typescript 错误。
不确定这是否正确,但我可能已经使用 solid-js 提供的children
助手 function找到了答案。
我的解决方案看起来像这样:
import { JSX, children as useChildren } from 'solid-js';
interface StuffProps {
children: JSX.Element
}
function Stuff({ children }: StuffProps) {
const c = useChildren(() => children).toArray()
<For each={c}> ... </For>
}
如果你不打算在某些效果中使用孩子,你可以直接用一些 JSX 元素包装孩子:
import { Component, JSXElement } from 'solid-js';
import { render } from 'solid-js/web';
const Stuff: Component<{ children: JSXElement }> = (props) => {
return (
<div><span>Wrapper:{props.children}</span></div>
)
};
const App = () => {
return (
<div>
<Stuff>
<h1>Some Title</h1>
</Stuff>
<Stuff>
<h1>Other Title</h1>
<p>Some paragraph</p>
</Stuff>
</div>
);
}
render(() => <App />, document.body);
在这里,我们有意避免解构 props,因为它会消除反应性,因为您会将它们分配给某个局部变量。 反应性通过 function 调用在组件之间传递。 但为了清楚起见,我暂时忽略这条规则。
如果你打算将props.children
与For
组件一起使用,你会得到错误,因为 children 不能保证是一个数组,因为 JSX 元素可以是任何number
| boolean
| Node
| JSX.ArrayElement
.数组元素 | JSX.FunctionElement
.函数元素 | (string & {})
| null
| undefined
。
所以,你需要确保 children 是一个数组:
import { render, } from 'solid-js/web';
import { Component, JSXElement } from 'solid-js';
const Stuff: Component<{ children: JSXElement }> = (props) => {
const children = Array.isArray(props.children) ? props.children : [props.children];
return (
<ul>
<li>{children.map(child => child)}</li>
</ul>
)
};
const App = () => {
return (
<div>
<Stuff>
<h1>Some Title</h1>
</Stuff>
<Stuff>
<h1>Other Title</h1>
<p>Some paragraph</p>
</Stuff>
</div>
);
}
render(() => <App />, document.body);
现在您可以将它与For
组件一起使用:
import { render, } from 'solid-js/web';
import { Component, For, JSXElement } from 'solid-js';
const Stuff: Component<{ children: JSXElement }> = (props) => {
const children = Array.isArray(props.children) ? props.children : [props.children];
return (
<ul>
<For each={children}>
{item => <li>{item}</li>}
</For>
</ul>
)
};
const App = () => {
return (
<div>
<Stuff>
<h1>Some Title</h1>
</Stuff>
<Stuff>
<h1>Other Title</h1>
<p>Some paragraph</p>
</Stuff>
</div>
);
}
render(() => <App />, document.body);
Solid 通过主库中的child
function 提供了这种便利,但如果将它们与For
组件一起使用,您仍然会遇到类型错误。 那是因为结果可能是false | readonly unknown[] | null | undefined
false | readonly unknown[] | null | undefined
false | readonly unknown[] | null | undefined
但这可以通过使用.toArray
方法而不是 function 调用来修复:
import { render, } from 'solid-js/web';
import { children, Component, For, JSXElement } from 'solid-js';
const Stuff: Component<{ children: JSXElement }> = (props) => {
const resolved = children(() => props.children);
return (
<ul>
<For each={resolved.toArray()}>
{item => <li>{item}</li>}
</For>
</ul>
)
};
const App = () => {
return (
<div>
<Stuff>
<h1>Some Title</h1>
</Stuff>
<Stuff>
<h1>Other Title</h1>
<p>Some paragraph</p>
</Stuff>
</div>
);
}
render(() => <App />, document.body);
正如我所说,这是访问儿童内部效果的一种便利。 提取它们只是为了包装在另一个元素中没有多大意义,因为你可以直接这样做,因为表达式是有效的 JSX 元素:
<div>{props.children}</div>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.