更新对17的React 17-打字条 - 反应节点类型的儿童不再处理内联条件渲染`void'

发布于 2025-01-25 09:02:30 字数 1722 浏览 4 评论 0原文

使用React.ReactNode 儿童的类型时,如果有任何内联条件渲染,它将失败。我目前正在使用swr获取数据,因此我会收到这样的错误:

 键入'false | void |元素|未定义的“不能分配为'reactnode'。
 键入“ void”不可分配给'reactnode'
 

我不确定是否以前React.ReactNode允许void,或者是否由于以前的隐式孩子而默默错过了。也许这是我应该对React或SWR开放的问题?

以前

我的React 17页组件看起来像这样。关于隐式儿童的破裂变化有很多信息,但我总是明确说明我的。也许是类型的孩子:voidundefinednull将被视为隐式的孩子吗?

type PageProps = {
  children: React.ReactNode
}

const Page = ({ children }: PageProps) = > {
  return (
    <div>
      <Header />

      <div>
        {children}
      </div>

      <Footer />
    </div>
  )
}

export default Page

问题

第一个问题“提供了多个孩子”

 这个JSX标签的“儿童'Prop都期望一个单身孩子
 “反应节点”,但提供了多个孩子。TS(2746)
 

修复

此类型允许多个或单身子女的这种类型的修复。我确实希望我们能在不明确或很多的情况下摆脱困境,但确实可以提供更强大的打字。

type PageProps = {
  children: React.ReactNode[] | React.ReactNode;
};

使用SWR失败的示例页面

const UsersPage: NextPage = () => {
  const { data, error } = useSWR('/api/user', fetcher)

  return (
    <Page>
      {users && (
        <pre>
          {JSON.stringify(users, null, 2)}
        </pre>
      )}
    </Page>
  )
}

将为我带来以下错误:

 键入'false | void |元素|未定义的“不能分配为'reactnode'。
 键入“ void”不可分配给键入'reactnode'
 

When using the React.ReactNode type for children if there are any inline conditional renders it will fail. I am currently using SWR to fetch data so I get an error like this:

Type 'false | void | Element | undefined' is not assignable to type 'ReactNode'.
 Type 'void' is not assignable to type 'ReactNode'

I'm not sure if previously React.ReactNode allowed void or if it was just silently missed due to implicit children before. Maybe this is an issue I should open up with React or SWR?

Previously

My React 17 Page component looked something like this previously. There is a lot of information around the breaking changes of implicit children but I always explicitly stated mine. Maybe a child of type: void, undefined, or null would be considered an implicit child though?

type PageProps = {
  children: React.ReactNode
}

const Page = ({ children }: PageProps) = > {
  return (
    <div>
      <Header />

      <div>
        {children}
      </div>

      <Footer />
    </div>
  )
}

export default Page

Problems

First Issue "multiple children were provided"

This JSX tag's 'children' prop expects a single child of type
 'ReactNode', but multiple children were provided.ts(2746)

Fix

That's fixed simply enough with this type that allows multiple or single children. I do wish we could get away without being explicit about or many, but it does give stronger typing.

type PageProps = {
  children: React.ReactNode[] | React.ReactNode;
};

Example Page Failing using SWR

const UsersPage: NextPage = () => {
  const { data, error } = useSWR('/api/user', fetcher)

  return (
    <Page>
      {users && (
        <pre>
          {JSON.stringify(users, null, 2)}
        </pre>
      )}
    </Page>
  )
}

This will give me the following error:

Type 'false | void | Element | undefined' is not assignable to type 'ReactNode'.
 Type 'void' is not assignable to type 'ReactNode'

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

久光 2025-02-01 09:02:30

选项1:将void添加到react> react node键入

一种方法是在类型上允许void这样:

type ReactNode = React.ReactNode | void;

type PageProps = {
  children: ReactNode[] | ReactNode;
};

发生错误,

您最终会出现给定上述实现page组件的混乱错误:

 这个JSX标签的“儿童'prop都期望一个'reactnode'的孩子,
 但是提供了多个孩子。TS(2746)
 

这令人困惑,因为它抱怨单身与多个孩子,但是,如果您从新键入中删除空白会很好,所以这似乎不是关于它是否是数组。

可以通过包装{children}呈现这样的效果来解决这:&lt;&gt; {children}&lt;/&gt;

示例

type ReactNode = React.ReactNode | void;

type PageProps = {
  children: ReactNode[] | ReactNode;
};

const Page = ({ children }: PageProps) = > {
  return (
    <div>
      <Header />

      <div>
        <>{children}</>
      </div>

      <Footer />
    </div>
  )
}

export default Page

>示例>示例选项2:处理void

另一个选项将是确保如果有条件的内联渲染返回void默认为空的react fragment(&lt;&gt;&gt;&lt;/&gt; )喜欢这样:

const UsersPage: NextPage = () => {
  const { data, error } = useSWR('/api/user', fetcher)

  return (
    <Page>
      {(users && (
        <pre>
          {JSON.stringify(users, null, 2)}
        </pre>
      )) || <></>}
    </Page>
  )
}

结尾笔记

,尽管选项2 可能被认为更“适当”,而不是覆盖和处理react> react node类型,但这将开始变得多余,感觉就像那时的反pates。 选项2 还需要您使用有条件渲染的任何地方更新。 选项1 修补它,以便您可以继续使用void返回。 不确定这是否有缺点

我 代码> void 然后您将遇到此问题,如果fetcher不返回void,则可以完全避免此问题,因为使用将返回回调值或未定义的 reactnode可以处理[undefinedfalsenull]。

如果使用wrr不返回void,您甚至不需要更改儿童属性组件。您只需将其保留为:儿童:React.ReaeActNode,因为React node Incord reactfragment是一个迭代的react> react> react> reactnode哪个包括单身或多个孩子。

React类型定义的React Node类型

  type reactnode = reactlement |字符串|数字|反应| ReactPortal |布尔| null |不明确的;
 

Option 1: Add void to the ReactNode type

One way would be to allow void on the type like so:

type ReactNode = React.ReactNode | void;

type PageProps = {
  children: ReactNode[] | ReactNode;
};

An Error Occurs

You will end up this confusing error given the above implementation of the Page component:

This JSX tag's 'children' prop expects a single child of type 'ReactNode',
 but multiple children were provided.ts(2746)

This is confusing because it's complaining about single vs multiple children, yet if you remove void from the new typing it will be fine, so this seems to not be about whether it's an array or not.

This can be resolved by wrapping the {children} render like so: <>{children}</>

Example

type ReactNode = React.ReactNode | void;

type PageProps = {
  children: ReactNode[] | ReactNode;
};

const Page = ({ children }: PageProps) = > {
  return (
    <div>
      <Header />

      <div>
        <>{children}</>
      </div>

      <Footer />
    </div>
  )
}

export default Page

Option 2: Handle the void

Another option would be to handle the void by making sure that if the conditional inline render returns void default to an empty React fragment (<></>) like so:

const UsersPage: NextPage = () => {
  const { data, error } = useSWR('/api/user', fetcher)

  return (
    <Page>
      {(users && (
        <pre>
          {JSON.stringify(users, null, 2)}
        </pre>
      )) || <></>}
    </Page>
  )
}

Closing Notes

Although Option 2 may be considered more "proper" rather than overriding and handling the ReactNode type, this would start to get redundant and feels like an anti-pattern at that point. Option 2 would also require you to update anywhere with a conditional render which gets cumbersome. Option 1 patches it so that you can continue utilizing void returns. I'm not certain if there is a downside to this

⭐️ A Further Dig ⭐️ -- The Real Answer ????

useSwr returns the types of the fetcher, if the fetcher returns void then you will run into this problem, if the fetcher does not return void then this problem can be avoided completely as useSWR will return the callback value or undefined which ReactNode can handle [undefined, false, null].

You will not even need to change the children property on the Page component if useSwr does not return void. You can simply keep it as: children: React.ReactNode since ReactNode includes ReactFragment which is an iterable ReactNode which includes single or multiple children.

ReactNode Type from React Type Definition

type ReactNode = ReactElement | string | number | ReactFragment | ReactPortal | boolean | null | undefined;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文