React-Typescript: This JSX tag's 'children' prop expects a single child of type 'Element | undefined', but multiple children were provided

Kri*_*sna 16 typescript react-typescript

I am using react-typescript for my app. For styling I am using Style component. I have decided I will create my custom Hooks Input and Password input. So I first created Input wrapper where I added necessary input fields. After that I have created Password input field. i extended my Password input component props with Input component props. But when I am using Input component wrapper to my password component. I am getting error: This JSX tag's 'children' prop expects a single child of type 'Element | undefined', but multiple children were provided.

I don't know what I am doing wrong.

这是我的输入包装组件

import React from "react";
import styled from "styled-components";
import ErrorBoundary from "components/errorBoundary";

const Container = styled.div`
  position: relative;
`;

const Label = styled.label<{ minimized?: boolean }>`
  display: block;
  color: ${({ theme }) => theme.inputLabelColor};
  font-weight: 400;
  font-size: ${({ minimized }) => (minimized ? "11px" : "16px")};
  margin-bottom: 5px;
  letter-spacing: -0.2px;
  position: absolute;
  transform: translateY(${({ minimized }) => (minimized ? "9px" : "16px")});
  left: 20px;
  top: 0;
  pointer-events: none;
  transition: transform 150ms linear, font-size 150ms linear;
`;

const Error = styled.p`
  color: ${({ theme }) => theme.errorTextColor};
`;

const Description = styled.p`
  color: blue;
`;

export interface IInputWrapperProps {
  label?: string;
  required?: boolean;
  minimizedLabel?: boolean;
  description?: string;
  error?: string;
  wrapperStyle?: React.CSSProperties;
  children?: JSX.Element;
}

export default ({
  label,
  error,
  description,
  children,
  required,
  wrapperStyle,
  minimizedLabel
}: IInputWrapperProps) => {
  return (
    <ErrorBoundary id="InputWrapperErrorBoundary">
      <div style={wrapperStyle}>
        <Container>
          <Label minimized={minimizedLabel}>
            {label} {required && <span style={{ color: "red" }}> *</span>}
          </Label>
          {children}
        </Container>
        {description && <Description>{description}</Description>}
        {error && <Error>{error}</Error>}
      </div>
    </ErrorBoundary>
  );
};
Run Code Online (Sandbox Code Playgroud)

这是我的密码组件

import React, { useState } from "react";
import styled from "styled-components";
import eyeHide from "./eye-svgfiles/eyeHide.svg";
import eyeShow from "./eye-svgfiles/eyeShow.svg";
import InputWrapper, { IInputWrapperProps } from "../wrapper";
const Passwordinput = styled.input`
  border: 2px solid ${({ theme }) => theme.inputBorderColorFaded};
  background: ${({ theme }) => theme.inputBackgroundColor};
  display: block;
  border-radius: 5px;
  box-shadow: none;
  color: ${({ theme }) => theme.inputTextColor};
  height: 52px;
  width: 100%;
  margin: 0;
  padding: 1px 15px;
  &:focus {
    border: 2px solid ${({ theme }) => theme.inputBorderColor};
    outline: 0;
  }
`;
const Svg = styled.div`
  position: absolute;
  left: 50%;
  top: 65%;
  transform: scale(0.8);
`;

export interface IPasswordProps extends IInputWrapperProps {
  onChange: (i: string) => void;
  value?: string | undefined;
}
export default ({ onChange, value, label, error, ...rest }: IPasswordProps) => {
  const [state, setstate] = useState(false);
  return (
    <div>
      <InputWrapper label={label} error={error} {...rest}> //I am getting error in here 
        <Passwordinput
          label={label}
          type={state ? "text" : "password"}
          onChange={e => onChange(e.target.value)}
          value={value}
          error={error}
        />
        <Svg>
          <img
            onClick={() => setstate(state => !state)}
            style={{ cursor: "pointer" }}
            src={state ? eyeShow : eyeHide}
            alt="searchIcon"
          />
        </Svg>
      </InputWrapper>
    </div>
  );
};
Run Code Online (Sandbox Code Playgroud)

小智 89

致所有 React 18 采用者

如果你刚刚升级到 React 18 并且你像我一样,你会React.PropsWithChildren<>到处添加,因为 props 的类型不再暗示children。如果您找到此线程,您可能会遇到我遇到的情况,其中一个随机组件似乎没有任何原因地给出了此错误,即使将多个元素作为children.

解决方案:

许多不同的东西都可以是“反应子元素”,包括许多原始类型,以及诸如undefinednull和之类的东西,false只是不渲染。我的组件是这样的:

<Container>
  {maybeNull && <Component notNullThing={maybeNull} />}
  {maybeNull2 && <Component notNullThing={maybeNull2} />}
  {maybeNull3 && <Component notNullThing={maybeNull3} />}
</Container>
Run Code Online (Sandbox Code Playgroud)

事实证明,maybeNull技术上有类型unknown,这让一切都失败了。我修复了它<>{maybeNull && <Component notNullThing={maybeNull} />}</>(因为由于某种原因单个unknown是合法的),尽管我也可以做{maybeNull ? <Component notNullThing={maybeNull} /> : null}或类似的事情。

认为这是因为 的类型React.ReactNode是一个包含 的大联合ReactFragment,它被递归地实现为Iterable<ReactNode>。这就是为什么 aReactNode可以是 s 的数组ReactNode。然而,unknown意味着你不知道它是联合体中的哪一个,所以你不知道它可能是Iterable<ReactNode>。类似 TypeScripty 的东西。

  • 谢谢,这有帮助。有一个更简单的修复方法:使用“!!”将“maybeNull”转换为布尔值 也许为空` (20认同)

小智 48

它可以通过以下方式修复:

interface InputWrapperProps {
  ...yourProps,
  children?: React.ReactNode
}
Run Code Online (Sandbox Code Playgroud)

希望有帮助!

  • 这是一个很好的答案,因为接受的答案在某些标准 React 用例中仍然可能会失败。有时孩子是一个布尔值!{变量&amp;&amp;&lt;元素/&gt;} (4认同)

Ami*_*rji 43

像这样编写你的界面:

export interface IInputWrapperProps {
  label?: string;
  required?: boolean;
  minimizedLabel?: boolean;
  description?: string;
  error?: string;
  wrapperStyle?: React.CSSProperties;
  children?: JSX.Element|JSX.Element[];
}
Run Code Online (Sandbox Code Playgroud)

事实上写作:

children: JSX.Element|JSX.Element[];
Run Code Online (Sandbox Code Playgroud)

子元素可以是单个 JSX 元素或元素数组。

  • 这应该被接受为正确答案 (6认同)

Gri*_*lov 39

对我来说 shuhat36 建议的变体效果很好。所以我只是为孩子们添加了片段。

错误示例:

<div className="container">
   {renderTabs()}
   {renderButtons()}
</div>
Run Code Online (Sandbox Code Playgroud)

和相同的代码但已修复:

<div className="container">
   <>
      {renderTabs()}
      {renderButtons()}
   </>
</div>
Run Code Online (Sandbox Code Playgroud)


小智 8

解决该错误的一种方法是使用片段来包装组件的子组件。这对我有用。


van*_*sun 5

已解决错误:TS2746:此 JSX 标记的“children”属性需要一个“ReactNode”类型的子项,但提供了多个子项。

方式:为儿童添加片段。

code: <p>Username: {loading ? 'Loading' : data}</p>
solved: add <></>
solved code: <p>Username: <>{loading ? 'Loading' : data}</></p>
Run Code Online (Sandbox Code Playgroud)