繁体   English   中英

如何使用 typescript 注释迭代 solid-js 子级

[英]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.childrenFor组件一起使用,你会得到错误,因为 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM