কখন JSX.Element বনাম ReactNode বনাম ReactElement ব্যবহার করবেন?


139

আমি বর্তমানে টাইপস্ক্রিপ্টে একটি প্রতিক্রিয়া অ্যাপ্লিকেশন স্থানান্তরিত করছি। এখনও অবধি, এটি বেশ ভালভাবে renderকাজ করে তবে আমার ফাংশনগুলির উপাদানগুলি যথাক্রমে আমার ফাংশনগুলির রিটার্নের ধরণের সাথে একটি সমস্যা আছে ।

এখনও অবধি, আমি সর্বদা JSX.Elementরিটার্নের ধরণ হিসাবে ব্যবহার করেছি , এখন কোনও উপাদান কোনও রেন্ডার না করার সিদ্ধান্ত নেয় , অর্থাত্ রিটার্ন null, কারণ nullএর কোনও বৈধ মান নেই JSX.Element। এটি আমার যাত্রার সূচনা ছিল, কারণ এখন আমি ওয়েবে অনুসন্ধান করেছি এবং দেখেছি যে এর ReactNodeপরিবর্তে আপনার ব্যবহার করা উচিত , এর মধ্যে রয়েছে nullএবং ঘটতে পারে এমন আরও কয়েকটি জিনিসও রয়েছে । এটি আরও ভাল বাজি বলে মনে হয়েছিল।

তবে, এখন কোনও ফাংশন উপাদান তৈরি করার সময়, টাইপস্ক্রিপ্ট ReactNodeটাইপ সম্পর্কে অভিযোগ করে । আবার, কিছু অনুসন্ধানের পরে আমি খুঁজে পেলাম যে ফাংশন উপাদানগুলির জন্য আপনার ReactElementপরিবর্তে ব্যবহার করা উচিত । যাইহোক, আমি যদি এটি করি তবে সামঞ্জস্যতা সমস্যাটি চলে গেছে তবে এখন টাইপসক্রিপ্ট আবার nullবৈধ মান না হওয়ার বিষয়ে অভিযোগ করে ।

সুতরাং, একটি দীর্ঘ গল্প সংক্ষিপ্ত কাটা, আমার তিনটি প্রশ্ন:

  1. মধ্যে পার্থক্য কি JSX.Element, ReactNodeএবং ReactElement?
  2. renderশ্রেণীর উপাদানগুলির পদ্ধতিগুলি কেন ফিরে আসে ReactNode, তবে ফাংশন উপাদানগুলি ফিরে আসে ReactElement?
  3. আমি কীভাবে শ্রদ্ধার সাথে এটি সমাধান করব null?

আমি অবাক হয়েছি এটি আসবে, যেহেতু সাধারণত আপনাকে উপাদানগুলির সাথে রিটার্নের ধরন নির্দিষ্ট করার প্রয়োজন হয় না। উপাদানগুলির জন্য আপনি কী ধরণের স্বাক্ষর করছেন? ভালো কিছু হওয়া উচিত class Example extends Component<ExampleProps> {শ্রেণীর জন্য, এবং const Example: FunctionComponent<ExampleProps> = (props) => {ফাংশন উপাদান জন্য (যেখানে ExamplePropsপ্রত্যাশিত সাজসরঞ্জাম জন্য একটি ইন্টারফেস)। এবং তারপরে এই ধরণের পর্যাপ্ত তথ্য রয়েছে যা রিটার্নের ধরণটি অনুমান করা যায়।
নিকোলাস টাওয়ার

প্রকারগুলি এখানে সংজ্ঞায়িত করা হয়েছে
জোনাস উইলস

4
@ নিকোলাসটওয়ার আমাদের আবদ্ধকরণের নিয়মগুলি সুস্পষ্টভাবে রিটার্নের প্রকার সরবরাহ করে, এবং এই কারণেই এটি সামনে আসে (যা আইএমএইচও হ'ল একটি ভাল বিষয়, কারণ আপনি কী করেন সে সম্পর্কে আপনি আরও কিছু ভাবেন যা বোঝার ক্ষেত্রে সহায়তা করে, যদি আপনি কেবল কম্পাইলারকে সবকিছু আবিষ্কার করতে দেন) ।
গোলো রোডেন

পর্যাপ্ত পরিমাণে, আমি লেটিং বিধি সম্পর্কে ভাবি নি।
নিকোলাস টাওয়ার

@ জোনাস উইলমস লিঙ্কটির জন্য ধন্যবাদ, তবে আমি মনে করি না যে এটি আমার প্রশ্নের উত্তর দেয়।
গোলো রোডেন

উত্তর:


151

জেএসএক্স.এলিমেন্ট, রি্যাক্টনোড এবং রিঅ্যাক্টেলমেন্টের মধ্যে পার্থক্য কী?

একটি রিঅ্যাক্ট এলিমেন্ট হ'ল একটি প্রকার এবং প্রপস সহ একটি বস্তু।

 interface ReactElement<P = any, T extends string | JSXElementConstructor<any> = string | JSXElementConstructor<any>> {
    type: T;
    props: P;
    key: Key | null;
}

একটি রিঅ্যাক্টনোড একটি রিঅ্যাক্টিমিলিটি, একটি রি্যাক্টফ্র্যাগমেন্ট, একটি স্ট্রিং, একটি সংখ্যা বা রি্যাক্টনোডগুলির একটি অ্যারে, বা নাল, বা অপরিজ্ঞাত বা বুলিয়ান:

type ReactText = string | number;
type ReactChild = ReactElement | ReactText;

interface ReactNodeArray extends Array<ReactNode> {}
type ReactFragment = {} | ReactNodeArray;

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

জেএসএক্স.এলিমেন্ট একটি প্রতিক্রিয়া উপাদান, প্রপসগুলির জন্য জেনেরিক টাইপ এবং টাইপ যে কোনও হ'ল। এটি বিদ্যমান, যেহেতু বিভিন্ন গ্রন্থাগারগুলি জেএসএক্সকে তাদের নিজস্ব উপায়ে প্রয়োগ করতে পারে, সুতরাং জেএসএক্স একটি বিশ্বব্যাপী নেমস্পেস যা লাইব্রেরির দ্বারা সেট হয়ে যায়, প্রতিক্রিয়াটি এটি সেট করে:

declare global {
  namespace JSX {
    interface Element extends React.ReactElement<any, any> { }
  }
}

উদাহরণস্বরূপ:

 <p> // <- ReactElement = JSX.Element
   <Custom> // <- ReactElement = JSX.Element
     {true && "test"} // <- ReactNode
  </Custom>
 </p>

শ্রেণীর উপাদানগুলির রেন্ডার পদ্ধতিগুলি কেন রিঅ্যাক্টনোড ফেরত দেয় তবে ফাংশন উপাদানগুলি রিঅ্যাক্টেলমেন্ট দেয়?

বস্তুতঃ তারা বিভিন্ন জিনিস ফিরিয়ে দেয়। Componentএর ফিরে:

 render(): ReactNode;

এবং ফাংশনগুলি হ'ল "রাষ্ট্রবিহীন উপাদান":

 interface StatelessComponent<P = {}> {
    (props: P & { children?: ReactNode }, context?: any): ReactElement | null;
    // ... doesn't matter
}

এটি আসলে historicalতিহাসিক কারণে

শূন্যের প্রতি শ্রদ্ধা সহ আমি কীভাবে এটি সমাধান করব?

ReactElement | nullপ্রতিক্রিয়া হিসাবে ঠিক এটি টাইপ করুন । অথবা টাইপসক্রিপ্টটি প্রকারটি অনুমান করতে দিন।

প্রকারের জন্য উত্স


বিস্তারিত উত্তর করার জন্য ধন্যবাদ! এটি পুরোপুরি প্রশ্নের 1 টির উত্তর দেয়, তবে এখনও 2 এবং 3 টি উত্তর উত্তর ছাড়েনি। আপনি কি দয়া করে তাদের সম্পর্কে কিছু গাইডেন্স প্রদান করতে পারেন?
গোলো রোডেন

@ গলোরোডেন নিশ্চিত, আমি এখনই কিছুটা ক্লান্ত হয়ে পড়েছি এবং একটি মোবাইলের ধরণগুলি স্ক্রোল করতে কিছুটা সময় লাগে ...;)
জোনাস উইলমস

হাই @ জোনাস উইলমস সম্পর্কিত "তারা করেন না। রিঅ্যাক্ট কম্পোনেন্টটিকে সংজ্ঞায়িত করা হয়: রেন্ডার (): জেএসএক্স.এলিমেন্ট | নাল | মিথ্যা;", আপনি কোথায় দেখছেন? দেখে মনে হচ্ছে এটি আমার কাছে রিট্যাক্টনোড দেয় ( github.com/DefinitelyTypeed/DefinitelyTypeed/blob/… ) এছাড়াও ছোটখাটো টাইপও আমার মনে হয় বা ReactComponentহওয়া উচিত । React.ComponentComponent
মার্ক ডলিনার

@ মার্কডোলিনার অদ্ভুত, আমি শপথ করতে পারি যে আমি এই ধরণের ফাইলটি অনুলিপি করে দিয়েছি ... যাই হোক না কেন, আপনি পুরোপুরি ঠিক বলেছেন, আমি সম্পাদনা করব
জোনাস উইলস

ছেলেরা ওয়েবে কোথাও প্রতিক্রিয়া && টাইপস্ক্রিপ্টের কোনও অফিসিয়াল ডকুমেন্টেশন আছে?
গোরান_আইলিক_লাইক

25

1.) জেএসএক্স.এলিমেন্ট, রিঅ্যাক্টনোড এবং রিঅ্যাক্টেলমেন্টের মধ্যে পার্থক্য কী?

প্রতিক্রিয়া এবং জেএসএক্স.এলিমেন্টReact.createElement সরাসরি বা জেএসএক্স প্রতিস্থাপনের মাধ্যমে প্রার্থনা করার ফলাফল । এটি একটি বস্তু type, propsএবং এর সাথে keyJSX.Elementহয় ReactElement, যার propsএবং typeপ্রকার থাকা any, তাই তারা বেশী বা কম একই।

const jsx = <div>hello</div>
const ele = React.createElement("div", null, "hello");

ReactNoderender() শ্রেণীর উপাদানগুলির জন্য রিটার্ন টাইপ হিসাবে ব্যবহৃত হয় । এটি childrenবৈশিষ্ট্যের সাথে ডিফল্ট টাইপও PropsWithChildren

const Comp: FunctionComponent = props => <div>{props.children}</div> 
// children?: React.ReactNode

প্রতিক্রিয়া প্রকারের ঘোষণাগুলিতে এটি আরও জটিল দেখায় তবে এর সমতুল্য :

type ReactNode = {} | null | undefined;
// super type `{}` has absorbed *all* other types, which are sub types of `{}`
// so it is a very "broad" type (I don't want to say useless...)

আপনি প্রায় সবকিছু বরাদ্দ করতে পারেন ReactNode। আমি সাধারণত শক্তিশালী ধরণের পছন্দ করি তবে এটি ব্যবহারের জন্য কিছু বৈধ কেস থাকতে পারে।


২) শ্রেণীর উপাদানগুলির রেন্ডার পদ্ধতিগুলি কেন রি্যাক্টনোড ফেরত দেয় তবে ফাংশন উপাদানগুলি রিঅ্যাক্টেলিমেন্ট ফেরত দেয়?

tl; dr: এটি একটি বর্তমান টিএস ধরণের বেমানান যা মূল প্রতিক্রিয়ার সাথে সম্পর্কিত নয় ।

  • টিএস শ্রেণীর উপাদান: প্রতিক্রিয়া / জেএসের চেয়ে আরও বেশি অনুমতিপ্রাপ্ত ReactNodeসাথে প্রত্যাবর্তনrender()

  • টিএস ফাংশন উপাদান: রিটার্ন JSX.Element | null/ জেএস এর চেয়ে বেশি প্রতিবন্ধক

নীতিগতভাবে, render()প্রতিক্রিয়া / জেএস শ্রেণিতে উপাদানগুলি ফাংশন উপাদান হিসাবে একই রিটার্নের ধরণগুলিকে সমর্থন করে । টিএস সম্পর্কিত, বিভিন্ন ধরণের হ'ল একধরণের অসঙ্গতি যা এখনও historicalতিহাসিক কারণে এবং পিছনে সামঞ্জস্যের প্রয়োজনীয়তার কারণে রাখা হয়।

আদর্শভাবে একটি বৈধ রিটার্ন টাইপ সম্ভবত আরও দেখতে হবে:

type ComponentReturnType = ReactElement | Array<ComponentReturnType> | string | number 
  | boolean | null // Note: undefined is invalid

৩) নালার সাথে আমি কীভাবে এটি সমাধান করব?

কিছু বিকল্প:
// Use type inference; inferred return type is `JSX.Element | null`
const MyComp1 = ({ condition }: { condition: boolean }) =>
    condition ? <div>Hello</div> : null

// Use explicit function return types; Add `null`, if needed
const MyComp2 = (): JSX.Element => <div>Hello</div>; 
const MyComp3 = (): React.ReactElement => <div>Hello</div>;  
// Option 3 is equivalent to 2 + we don't need to use a global (JSX namespace)

// Use built-in `FunctionComponent` or `FC` type
const MyComp4: React.FC<MyProps> = () => <div>Hello</div>;

দ্রষ্টব্য: এড়ানো এড়ানো React.FC আপনাকেJSX.Element | null রিটার্নের ধরণের সীমাবদ্ধতা থেকে রক্ষা করবে না

তৈরি প্রতিক্রিয়া অ্যাপ্লিকেশনটি এর টেম্পলেট থেকে সম্প্রতি বাদ পড়েছেReact.FC , কারণ এতে কিছু অন্তর্নিহিত {children?: ReactNode}ধরণের সংজ্ঞা রয়েছে। তাই React.FCঅল্প পরিমাণে ব্যবহার করা পছন্দনীয় হতে পারে।

প্রান্তের ক্ষেত্রে, আপনি এক ধরণের যুক্তি বা টুকরো টুকরো যোগ করতে পারেন:
const MyCompFragment: FunctionComponent = () => <>"Hello"</>
const MyCompCast: FunctionComponent = () => "Hello" as any 
// alternative to `as any`: `as unknown as JSX.Element | null`
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.