React-Typescript: Das 'children'-Prop dieses JSX-Tags erwartet ein einzelnes Kind vom Typ 'Element | undefined', aber mehrere Kinder wurden bereitgestellt
Ich verwende React-TypeScript für meine App. Für das Styling verwende ich Style-Komponenten. Ich habe beschlossen, dass ich meine eigenen Hooks Input und Password Input erstellen werde. Also habe ich zuerst einen Input-Wrapper erstellt, in den ich die notwendigen Eingabefelder hinzugefügt habe. Danach habe ich das Password-Eingabefeld erstellt. Ich habe die Props meines Password-Input-Komponenten um die Props des Input-Komponenten erweitert. Aber wenn ich den Input-Komponenten-Wrapper für meine Password-Komponente verwende, erhalte ich den Fehler: Dieser JSX-Tag erwartet für die 'children'-Prop ein einzelnes Kind vom Typ 'Element | undefined', aber mehrere Kinder wurden bereitgestellt.
Ich weiß nicht, was ich falsch mache.
Dies ist meine Input-Wrapper-Komponente
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>
);
};
Dies ist meine Passwortkomponente
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>
);
};
Antwort #1
Schreiben Sie Ihre Schnittstelle so:
export interface IInputWrapperProps {
label?: string;
required?: boolean;
minimizedLabel?: boolean;
description?: string;
error?: string;
wrapperStyle?: React.CSSProperties;
children?: JSX.Element|JSX.Element[];
}
tatsächlich schreiben:
children: JSX.Element|JSX.Element[];
Die Kinder können entweder ein einzelnes JSX-Element oder ein Array von Elementen sein.
Antwort #2
An alle React-18-Anwender da draußen
Wenn Sie gerade auf React 18 aktualisiert haben und wie ich sind, fügen Sie überall React.PropsWithChildren<> hinzu, da die Typen für Props nicht mehr automatisch children implizieren. Wenn Sie auf diesen Thread stoßen, sind Sie wahrscheinlich auf das gestoßen, was mir passiert ist, dass eine zufällige Komponente diesen Fehler ohne ersichtlichen Grund ausgegeben hat, obwohl es völlig legal ist, mehrere Elemente als children zu haben.
LÖSUNG:
Viele verschiedene Dinge können „React-Kinder“ sein, einschließlich vieler primitiver Typen, und Dinge wie undefined, null und false werden einfach nicht gerendert. Meine Komponente sah ungefähr so aus:
<Container>
{maybeNull && <Component notNullThing={maybeNull} />}
{maybeNull2 && <Component notNullThing={maybeNull2} />}
{maybeNull3 && <Component notNullThing={maybeNull3} />}
</Container>
Es stellte sich heraus, dass maybeNull technisch den Typ unknown hatte, und das hat alles durcheinandergebracht. Ich habe es mit <>{maybeNull && <Component notNullThing={maybeNull} />}</> behoben (weil ein einzelner unknown aus irgendeinem Grund erlaubt ist), obwohl ich auch {maybeNull ? <Component notNullThing={maybeNull} /> : null} oder etwas Ähnliches hätte machen können.
Ich denke, es liegt daran, dass der Typ von React.ReactNode eine große Vereinigung ist, die ReactFragment einschließt, das rekursiv als Iterable<ReactNode> implementiert ist. Deshalb kann ein ReactNode ein Array von ReactNodes sein. unknown bedeutet jedoch, dass man nicht weiß, welches der Dinge in der Vereinigung es ist, also weiß man nicht, dass es Iterable<ReactNode> sein könnte. Etwas TypeScript-artiges in der Art.
Antwort #3
Es kann behoben werden mit:
interface InputWrapperProps {
...yourProps,
children?: React.ReactNode
}
Hoffe, es hilft!
Antwort #4
Für mich funktioniert die von shuhat36 vorgeschlagene Variante gut. Also habe ich einfach einen Abschnitt für Kinder hinzugefügt.
Beispiel mit Fehler:
<div className="container">
{renderTabs()}
{renderButtons()}
</div>
Und derselbe Code, aber korrigiert:
<div className="container">
<>
{renderTabs()}
{renderButtons()}
</>
</div>
