मैं टाइपस्क्रिप्ट में वास्तविक "यदि" की तरह कार्य करने वाला एक रिएक्ट "इफ़" घटक कैसे बना सकता हूं?


11

मैंने <If />रिएक्ट का उपयोग करते हुए एक साधारण फ़ंक्शन घटक बनाया :

import React, { ReactElement } from "react";

interface Props {
    condition: boolean;
    comment?: any;
}

export function If(props: React.PropsWithChildren<Props>): ReactElement | null {
    if (props.condition) {
        return <>{props.children}</>;
    }

    return null;
}

यह मुझे एक क्लीनर कोड लिखने देता है, जैसे:

render() {

    ...
    <If condition={truthy}>
       presnet if truthy
    </If>
    ...

ज्यादातर मामलों में, यह अच्छा काम करता है, लेकिन जब मैं उदाहरण के लिए जांच करना चाहता हूं कि क्या किसी दिए गए चर को परिभाषित नहीं किया गया है और फिर इसे संपत्ति के रूप में पारित किया जाता है, तो यह एक मुद्दा बन जाता है। मैं एक उदाहरण दूंगा:

मान लीजिए कि मेरे पास एक घटक है जिसे <Animal />निम्नलिखित प्रॉप्स कहते हैं:

interface AnimalProps {
  animal: Animal;
}

और अब मेरे पास एक और घटक है जो निम्नलिखित DOM को प्रस्तुत करता है:

const animal: Animal | undefined = ...;

return (
  <If condition={animal !== undefined} comment="if animal is defined, then present it">
    <Animal animal={animal} /> // <-- Error! expected Animal, but got Animal | undefined
  </If>
);

जैसा कि मैंने टिप्पणी की है, वास्तव में पशु को परिभाषित नहीं किया गया है, मुझे टाइपस्क्रिप्ट को बताने का कोई तरीका नहीं मिला है कि मैंने इसे पहले ही जांच लिया है। animal!काम करने का आश्वासन दिया जाएगा, लेकिन यह वह नहीं है जिसकी मुझे तलाश है।

कोई विचार?


1
यकीन है कि अगर यह टाइपस्क्रिप्ट में संभव है, तो उसे बताएं कि आप पहले से ही अशक्त सुरक्षा को चबाते हैं। शायद {animal !== undefined && <Anibal animal={animal} />}काम करेगा
ओलिवियर बोइस

1
क्या यह काम करता है? <Animal animal={animal as Animal} />
पॉल

@ OlivierBoissé मैं उस वाक्य रचना का उपयोग करने से प्रतिबंधित हूँ
एलिया कोहेन

@ अंपुल हां, लेकिन यह "" के समान नहीं होगा! अंततः?
एलिया कोहेन

जवाबों:


3

यह असंभव लगता है।

कारण: यदि हम Ifघटक की सामग्री को बदलते हैं

if (props.condition) {
  ...
}

यह विपरीत है

if (!props.condition) {
  ...
}

आपको पता चल जाएगा कि इस बार आप चाहते हैं कि टाइप विपरीत तरीके से संसाधित हो।

  <If condition={animal === undefined} comment="if animal is defined, then present it">
    <Animal animal={animal} /> // <-- Error! expected Animal, but got Animal | undefined
  </If>

इसका मतलब यह है कि यह स्वतंत्र नहीं है, जिससे यह निष्कर्ष निकलता है कि इस प्रकार की भिन्नता इस स्थिति में संभव नहीं है, दोनों घटकों में से किसी को स्पर्श किए बिना।


मुझे यकीन नहीं है कि सबसे अच्छा तरीका क्या है, लेकिन यहां मेरा एक विचार है।

आप निर्धारित कर सकते हैं Animal componentके रंगमंच की सामग्री animalटाइपप्रति के साथ
वितरण सशर्त प्रकार : NonNullable

दस्तावेज़

type T34 = NonNullable<string | number | undefined>;  // string | number

प्रयोग

interface AnimalProps {
  // Before
  animal: Animal;
  // After
  animal: NonNullable<Animal>;
}

यह Ifघटक की स्थिति से उत्पन्न नहीं होता है , लेकिन चूंकि आप केवल child componentउस स्थिति के अंदर का उपयोग करते हैं, इसलिए यह इस शर्त के तहत , के child componentरूप में सहारा को डिजाइन करने के लिए कुछ समझ में आता है none nullableकि

प्रकार Animalहोते हैं undefined


मुझे यकीन नहीं है कि यह मेरी समस्या को कैसे हल करता है। पशु घटक में If घटक से संबंधित कुछ भी नहीं है। यदि यह घटक से मेल खाने के लिए इसे स्वयं को अनुकूल नहीं बनाना चाहिए। इसके अलावा, मुझे यकीन नहीं है कि मेरी समस्या के बारे में नॉनन्यूलेबल का कुछ भी काम नहीं है
एलिया कोहेन

@EliyaCohen अपडेट किया गया, इस उत्तर के लिए कुछ भी करने की आवश्यकता है?
कीकाई

मैंने आपके उत्तर को स्वीकार कर लिया है, हालाँकि मैं इसे स्वीकार नहीं कर सकता क्योंकि यह समाधान नहीं है। संभवतः भविष्य में हल हो जाएगा जब टीएस और रिएक्ट इस तरह की चीज को संभव बनाएंगे।
एलिया कोहेन

1

संक्षिप्त जवाब?

आप नहीं कर सकते।

चूंकि आपने परिभाषित animalकिया है Animal | undefined, हटाने undefinedका एकमात्र तरीका या तो एक गार्ड बनाना है या animalकुछ और के रूप में फिर से तैयार करना है। आप अपनी हालत संपत्ति में टाइप गार्ड छिपा हुआ है, और इसलिए यह पता नहीं कर सकते हैं के बीच चयन कर रहे हैं टाइपप्रति, जानते हुए भी कि वहाँ क्या हो रहा है का कोई रास्ता नहीं है Animalऔर undefined। आपको इसे डालने या उपयोग करने की आवश्यकता होगी !

विचार करें, हालांकि: यह क्लीनर महसूस कर सकता है, लेकिन यह कोड का एक टुकड़ा बनाता है जिसे समझने और बनाए रखने की आवश्यकता होती है, शायद किसी और ने लाइन के नीचे। संक्षेप में, आप एक नई भाषा बना रहे हैं, जो रिएक्ट घटकों से बना है, जिसे टाइपस्क्रिप्ट के अलावा किसी को सीखना होगा।

जेएसएक्स को सशर्त रूप से आउटपुट करने के लिए एक वैकल्पिक तरीका यह है renderकि चर को अपनी सशर्त सामग्री जैसे कि परिभाषित करें

render() {
  const conditionalComponent = condition ? <Component/> : null;

  return (
    <Zoo>
      { conditionalComponent }
    </Zoo>
  );
}

यह एक मानक दृष्टिकोण है जो अन्य डेवलपर्स तुरन्त पहचान लेंगे और उन्हें नहीं देखना होगा।


0

एक रेंडरबैक कॉलबैक का उपयोग करके, मैं टाइप कर सकता हूं कि रिटर्न पैरामीटर अशक्त नहीं है।

मैं आपके मूल Ifघटक को संशोधित करने में सक्षम नहीं हूं क्योंकि मुझे नहीं पता कि आपके conditionमुखर क्या हैं और यह भी कि यह किस चर के रूप में हैcondition={animal !== undefined || true}

इसलिए दुर्भाग्य से, मैंने IsDefinedइस मामले को संभालने के लिए एक नया घटक बनाया :

interface IsDefinedProps<T> {
  check: T;
  children: (defined: NonNullable<T>) => JSX.Element;
}

function nonNullable<T>(value: T): value is NonNullable<T> {
  return value !== undefined || value !== null;
}

function IsDefined({ children, check }: IsDefinedProps<T>) {
  return nonNullable(check) ? children(check) : null;
}

यह इंगित करते हुए कि childrenएक कॉलबैक होगा, जिसे T के एक गैर-प्रकार से पास किया जाएगा जो कि उसी प्रकार का है check

इसके साथ, हम एक रेंडर कॉलबैक प्राप्त करेंगे, जो एक अशक्त-चेक किया गया चर होगा।

  const aDefined: string | undefined = mapping.a;
  const bUndefined: string | undefined = mapping.b;

  return (
    <div className="App">
      <IsDefined check={aDefined}>
        {aDefined => <DoSomething message={aDefined} />} // is defined and renders
      </IsDefined>
      <IsDefined check={bUndefined}>
        {bUndefined => <DoSomething message={bUndefined} />} // is undefined and doesn't render
      </IsDefined>
    </div>
  );

मेरे पास यहां एक वर्किंग उदाहरण है https://codesandbox.io/s/blazing-pine-2t4sm


यह एक अच्छा तरीका है, लेकिन दुर्भाग्य से यह Ifघटक का उपयोग करने के पूरे उद्देश्य को हरा देता है (ताकि यह साफ दिख सके)
एलिया कोहेन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.