如何使用打字稿注释迭代solid-js子级

ugl*_*nky 4 loops for-loop typescript solid-js

假设我有以下组件,我将如何迭代并渲染每个子组件以执行诸如用其他组件包装每个子组件之类的操作?

interface StuffProps {
  children: `?`
}

function Stuff({ children }: StuffProps) {
  // ?
}
Run Code Online (Sandbox Code Playgroud)

我尝试过设置children: JSX.Element然后执行<For each={children}> ... </For>,但它给了我一个打字稿错误。

snn*_*snn 5

如果你不打算在某些效果中使用子元素,你可以直接用一些 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);
Run Code Online (Sandbox Code Playgroud)

在这里,我们故意避免解构 props,因为这会消除反应性,因为您将把它们分配给一些局部变量。反应性通过函数调用在组件之间传输。但为了清楚起见,我现在将忽略这条规则。

如果您要props.childrenFor组件一起使用,您将收到错误,因为不能保证孩子是一个数组,因为 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);
Run Code Online (Sandbox Code Playgroud)

现在您可以将它与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);
Run Code Online (Sandbox Code Playgroud)

Solid 通过children主库中的函数提供了这种便利,但如果将它们与For组件一起使用,您仍然会遇到类型错误。这是因为结果可能是false | readonly unknown[] | null | undefined,但这可以通过使用.toArray方法而不是函数调用来修复:

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);
Run Code Online (Sandbox Code Playgroud)

正如我所说,这是访问儿童内部效果的便利。仅提取它们以包装在另一个元素中没有多大意义,因为您可以直接这样做,因为表达式是有效的 JSX 元素:

<div>{props.children}</div>
Run Code Online (Sandbox Code Playgroud)