टाइपस्क्रिप्ट और प्रतिक्रिया - बच्चे टाइप?


138

मेरे पास एक बहुत ही सरल कार्यात्मक घटक है:

import * as React from 'react';

export interface AuxProps  { 
    children: React.ReactNode
 }


const aux = (props: AuxProps) => props.children;

export default aux;

और एक अन्य घटक:

import * as React from "react";

export interface LayoutProps  { 
   children: React.ReactNode
}

const layout = (props: LayoutProps) => (
    <Aux>
        <div>Toolbar, SideDrawer, Backdrop</div>
        <main>
            {props.children}
        </main>
    <Aux/>
);

export default layout;

मैं निम्नलिखित त्रुटि प्राप्त करता रहता हूं:

[ts] JSX तत्व प्रकार 'ReactNode' JSX तत्वों के लिए एक रचनाकार कार्य नहीं है। 'ElementClass' टाइप करने के लिए 'अपरिभाषित' टाइप करना उचित नहीं है। [2605]

मैं इसे सही तरीके से कैसे लिखूं?

जवाबों:


133

केवल children: React.ReactNode


1
यह यहाँ सही उत्तर है! JSX.Elementकाफी अच्छा नहीं है क्योंकि एक वैध रिएक्ट बच्चे एक स्ट्रिंग, एक बूलियन, अशक्त हो सकते हैं ... ReactChildएक ही कारण के लिए भी अधूरा है
पियरे फेरी

2
@PierreFerry मुद्दा यह है कि लगभग कुछ भी सौंपा जा सकता है ReactNode। यह प्रकार सुरक्षा, टाइपिंग के लिए इसी तरह के मामले में मदद नहीं करता है childrenके रूप में any- मेरे देखने जवाब स्पष्टीकरण के लिए।
ford04

आपकी प्रतिक्रिया के लिए धन्यवाद @ ford04 मेरे उपयोग के मामले में मैं चाहता हूं कि बच्चे शिथिल टाइप के हों। मेरा घटक किसी भी प्रकार के वैध रिएक्ट बच्चों को स्वीकार करता है। तो मुझे विश्वास है कि यह अभी भी जवाब है जो मैं ढूंढ रहा था :)
पियरे फेरी

47

<Aux>अपने JSX में उपयोग करने के लिए , यह एक फ़ंक्शन होना चाहिए जो रिटर्न करता है ReactElement<any> | null। यह एक फ़ंक्शन घटक की परिभाषा है ।

हालाँकि, इसे वर्तमान में एक फ़ंक्शन के रूप में परिभाषित किया गया है जो रिटर्न करता है React.ReactNode, जो कि बहुत व्यापक प्रकार है। जैसा कि रिएक्ट टाइपिंग कहते हैं:

type ReactNode = ReactChild | ReactFragment | ReactPortal | boolean | null | undefined;

सुनिश्चित करें कि रिएक्ट फ्रैगमेंट ( <></>) में दिए गए मान को लपेटकर अवांछित प्रकारों को बेअसर कर दिया जाता है :

const aux: React.FC<AuxProps> = props =>
  <>{props.children}</>;

मुझे समझ में नहीं आ रहा है कि childrenरिएक्ट फ्रैगमेंट में लपेटने की आवश्यकता क्यों है । समझाने की परवाह? प्रतिक्रिया में यह सिर्फ करने के लिए पूरी तरह से मान्य है return children;
sanfilippopablo

1
नहीं अगर childrenएक सरणी हैं। अगर ऐसा है तो आपको उन्हें एक ही नोड में लपेटने या रिएक्ट फ्रैगमेंट का उपयोग करने की आवश्यकता है।
करोल माजवेस्की

हाँ, मेरे कोड में मेरे पास है: return React.Children.count(children) > 1 ? <>{children}</> : childrenलेकिन टाइपस्क्रिप्ट उस के बारे में शिकायत करता है। मैंने इसे बस के साथ बदल दिया <>{children}</>
सैनफिलिपोपब्लो

2
यह शिकायत करता है क्योंकि childrenतत्वों की एक सूची है जो केवल 1 आइटम को शामिल करने के लिए होती है। मुझे लगता है कि अगर आप return React.Children.count(children) > 1 ? <>{children}</> : children[0]@sanfilippopablo
tamj0rd2

यह प्रतिक्रिया के नए संस्करणों में काम करता नहीं दिखाई देता है। मैंने लॉग इन कंसोल किया है और पुष्टि कर सकता हूं कि मेरे पास एक बच्चा है, लेकिन <React.Fragment>आसपास के साथ भी {props.children}मैं कुछ भी नहीं लौटा रहा हूं।
मार्क

34

इसी से मेरा काम बना है:

interface Props {
  children: JSX.Element[] | JSX.Element
}

संपादित करें मैं children: React.ReactNodeअब के बजाय का उपयोग करने की सिफारिश करेंगे ।


8
यह एक परिभाषा के लिए पर्याप्त नहीं है। बच्चा एक तार हो सकता है।
माइक एस

कम से कम इस उदाहरण ने मेरे लिए काम किया क्योंकि मेरे घटक को 1 या अधिक JSX.Elements की उम्मीद थी। धन्यवाद!
इटालो बोर्गेस

1
यह बच्चों के रूप में जावास्क्रिप्ट अभिव्यक्तियों के साथ काम नहीं करेगा <MyComponent>{ condition ? <span>test</span> : null}</MyComponent>। का उपयोग करते हुए children: ReactNodeकाम करेंगे।
निकोफिथिम

10

आप अपने घटक को इस तरह घोषित कर सकते हैं:

const MyComponent: React.FunctionComponent = (props) => {
    return props.children;
}

9

आप उपयोग कर सकते हैं ReactChildrenऔर ReactChild:

import React, { ReactChildren, ReactChild } from 'react';

interface AuxProps {
  children: ReactChild | ReactChildren;
}

const Aux = ({ children }: AuxProps) => (<div>{children}</div>);

export default Aux;

6

टाइपस्क्रिप्ट साइट से: https://github.com/Microsoft/TypeScript/issues/6471

सुझाए गए अभ्यास को प्रॉप्स टाइप को {बच्चे ?: कोई} लिखना है

मेरे लिए यही काम किया। बाल नोड कई अलग-अलग चीजें हो सकती हैं, इसलिए स्पष्ट टाइपिंग मामलों को याद कर सकती है।

यहां फॉलोअप मुद्दे पर एक लंबी चर्चा है: https://github.com/Microsoft/TypeScript/issues/13618 , लेकिन कोई भी दृष्टिकोण अभी भी काम करता है।


6

फ़ंक्शन घटक वापसी प्रकार JSXElement | nullटाइपस्क्रिप्ट में सीमित है । यह एक वर्तमान प्रकार की सीमा है, शुद्ध प्रतिक्रिया अधिक वापसी प्रकारों की अनुमति देती है

न्यूनतम प्रदर्शन स्निपेट

आप या तो वर्कअराउंड के रूप में एक प्रकार का अभिकथन या अंश का उपयोग कर सकते हैं:

const Aux = (props: AuxProps) => <>props.children</>; 
const Aux2 = (props: AuxProps) => props.children as ReactElement; 

ReactNode

children: React.ReactNodeयदि लक्ष्य के लिए मजबूत प्रकार है, तो इसे अपनाना होगा Aux

लगभग कुछ भी वर्तमान ReactNodeप्रकार को सौंपा जा सकता है , जो इसके बराबर है {} | undefined | null। आपके मामले के लिए एक सुरक्षित प्रकार हो सकता है:

interface AuxProps {
  children: ReactElement | ReactElement[]
}

उदाहरण:

यह देखते हुए Auxकी जरूरत तत्व के रूप में प्रतिक्रिया children, हम गलती से एक जोड़ा stringइसे करने के लिए। फिर उपरोक्त समाधान इसके विपरीत त्रुटि करेगा ReactNode- लिंक किए गए खेल के मैदानों पर एक नज़र डालें।

टाइप childrenनॉन-जेएसएक्स प्रॉप्स के लिए भी उपयोगी हैं, जैसे रेंडर प्रोप कॉलबैक।


5

आप भी इस्तेमाल कर सकते हैं React.PropsWithChildren<P>

type ComponentWithChildProps = React.PropsWithChildren<{example?: string}>;

3

किसी भी प्रकार को खोजने का सामान्य तरीका उदाहरण के द्वारा है। टाइपस्क्रिप्ट की सुंदरता यह है कि आपके पास सभी प्रकारों तक पहुंच है , इसलिए जब तक आपके पास सही @types/फाइलें हैं।

इसका जवाब देने के लिए मैंने सिर्फ एक घटक प्रतिक्रिया का उपयोग किया है जिसके बारे में सोचा है children। पहली बात जो मन में आई? कैसे के बारे में <div />?

आपको बस vscode को ओपन करना है और इसके .tsxसाथ एक रिएक्शन प्रोजेक्ट में एक नई फाइल बनानी है @types/react

import React from 'react';

export default () => (
  <div children={'test'} />
);

childrenप्रोप पर मँडरा आपको प्रकार दिखाता है। और आप क्या जानते हैं - इसका प्रकार है ReactNode(कोई ज़रूरत नहीं है ReactNode[])।

यहां छवि विवरण दर्ज करें

फिर यदि आप टाइप परिभाषा में क्लिक करते हैं तो यह आपको इंटरफ़ेस childrenसे आने की परिभाषा में सीधे लाता DOMAttributesहै।

// node_modules/@types/react/index.d.ts
interface DOMAttributes<T> {
  children?: ReactNode;
  ...
}

नोट: इस प्रक्रिया का उपयोग किसी भी अज्ञात प्रकार को खोजने के लिए किया जाना चाहिए! उन सभी को वहाँ बस आप उन्हें खोजने के लिए इंतजार कर रहे हैं :)


2

एक प्रकार जिसमें बच्चे होते हैं, मैं उपयोग कर रहा हूं:

type ChildrenContainer = Pick<JSX.IntrinsicElements["div"], "children">

यह बच्चों के कंटेनर प्रकार सभी विभिन्न मामलों का समर्थन करने के लिए काफी सामान्य है और यह रिएक्टजस एपीआई के साथ भी जुड़ा हुआ है।

तो, आपके उदाहरण के लिए यह कुछ इस तरह होगा:

const layout = ({ children }: ChildrenContainer) => (
    <Aux>
        <div>Toolbar, SideDrawer, Backdrop</div>
        <main>
            {children}
        </main>
    <Aux/>
)

1

ये उत्तर पुराने प्रतीत होते हैं - प्रतिक्रिया अब एक निर्मित प्रकार की है PropsWithChildren<{}>। इसे इस पृष्ठ के कुछ सही उत्तरों के समान परिभाषित किया गया है:

type PropsWithChildren<P> = P & { children?: ReactNode };


1
Pउस प्रकार के मामले में क्या है ?
Sunpietro

Pआपके घटक के प्रकार का प्रकार है
टिम इल्स

-2

प्रतिक्रिया घटकों में एक ही आवरण नोड होना चाहिए या नोड्स की एक सरणी वापस करना चाहिए।

आपके <Aux>...</Aux>घटक में दो नोड्स divऔर हैं main

एक में अपने बच्चों को रैप करने के लिए प्रयास करें divमें Auxघटक।

import * as React from 'react';

export interface AuxProps  { 
  children: React.ReactNode
}

const aux = (props: AuxProps) => (<div>{props.children}</div>);

export default aux;

1
सच नहीं। रिएक्ट 16+ में अब ऐसा नहीं है, साथ ही त्रुटि यह कहेगी यदि यह मामला था
एंड्रयू ली
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.