Definitelytyped: يجب أن تعيد مكونات التفاعل ReactNode ، أو يجب أن تكون العناصر الفرعية ReactElement

تم إنشاؤها على ١٤ يوليو ٢٠١٧  ·  18تعليقات  ·  مصدر: DefinitelyTyped/DefinitelyTyped

  • [x] حاولت استخدام الحزمة @types/react وواجهت مشاكل.
  • [x] حاولت استخدام أحدث إصدار مستقر من tsc. https://www.npmjs.com/package/typescript
  • [x] لدي سؤال غير مناسب لـ StackOverflow . (يرجى طرح أي أسئلة مناسبة هناك).
  • [x] [أذكر] (https://github.com/blog/821-mention-somebody-they-re-notified) المؤلفون (انظر Definitions by: في index.d.ts ) حتى يتمكنوا من رد.

    • المؤلفون : ericanderson onigoetztkrotoffdigigurumorcerfjohnnyreillybenezechpzavolinskyDovydasNavickas _ _ _ _ _

المكونات التالية

const SFC: React.StatelessComponent = (props) => props.children;

class C extends React.Component {
  render() {
    return this.props.children;
  }
}

اعطاء الاخطاء

Type '(props: { children?: ReactNode; }) => ReactNode' is not assignable to type 'StatelessComponent<{}>'.
  Type 'ReactNode' is not assignable to type 'ReactElement<any> | null'.
    Type 'undefined' is not assignable to type 'ReactElement<any> | null'.

Class 'C' incorrectly extends base class 'Component<{}, {}>'.
  Types of property 'render' are incompatible.
    Type '() => ReactNode' is not assignable to type '() => false | Element | null'.
      Type 'ReactNode' is not assignable to type 'false | Element | null'.
        Type 'undefined' is not assignable to type 'false | Element | null'.

يعمل إذا قمت بلف children بـ Element .

يعد إرجاع children أمرًا شائعًا عند إنشاء مكونات المزود التي تضيف شيئًا إلى context .

التعليق الأكثر فائدة

أقوم حاليًا بلف children بـ React.Fragment للتغلب على هذا.

ال 18 كومينتر

لقد جربت الإصلاحات التالية لـ index.d.ts

-        render(): JSX.Element | null | false;
+        render(): ReactNode;

-        (props: P & { children?: ReactNode }, context?: any): ReactElement<any> | null;
+        (props: P & { children?: ReactNode }, context?: any): ReactNode;

لكنني حصلت على أخطاء في كل مكان عند محاولتي التعرّف على أنني لست متأكدًا من كيفية إصلاحها.

TypeScript compile error: JSX element type 'ReactNode' is not a constructor function for JSX elements.

كلا ، هذا التغيير غير صحيح. لا يمكنك إرجاع عناصر متعددة في React حاليًا. حتى لو قمت بذلك في مكان ما ، فمن المحتمل أنه يتم تغليفه في مكان واحد بطريقة ما.
فقط في React 16 باستخدام الألياف قد يكون هذا ممكنًا :)

لست متأكدًا مما إذا كانوا قد غيروا سلوك التفاعل ، لكن مؤلف إعادة الإرسال / رد الفعل أظهر القدرة على إرجاع this.props.children لإنشاء أغلفة رقيقة (فقط لإضافة childContext إلى العناصر) ، كما هو موضح في https://egghead.io/lessons/ javascript-redux-pass-the-store-down-ضمنيًا عبر السياق

يتيح لك رد الفعل الأصلي إمكانية إرجاع مصفوفة من عناصر JSX من التصيير ، على الرغم من ذلك. حل بديل هو التفاف this.props.children بـ React.Children.only(this.props.children) وسيتم طرحه إذا كان هناك أكثر من عنصر واحد كجذر

حسنًا ، يمكنك استخدام React.Children.only لكن كلاهما ReactNode و ReactElement قيمتان صالحتان لـ this.props.children .

const Title = props => <h1>{props.children}</h1>;
<Title>Woah</Title>

هو كود رد صالح ومعقول.

يمكنك إرجاع مصفوفة من العناصر في رد الفعل 16 ، لكن TS يُلقي بخطأ لأنه يعتقد أنك غير قادر على ذلك.

تحرير: قم بهذا children: JSX.Element[]; لإصلاحه

من تجربتي حتى الآن ، يبدو أن ReactNode يجب أن تكون صالحة.

const Id: React.SFC<{}> = (props) => props.children

const App = ()= > <Id>This should work but instead fails</Id>

هل هناك أي احتمال أن ينعكس ذلك في @types/react ؟

بدون هذا لا أستطيع كتابة أطفال React

أقوم حاليًا بلف children بـ React.Fragment للتغلب على هذا.

أي تحديثات على ذلك؟

لست متأكدًا مما إذا كان هذا أكثر أو أقل صحة من تغليف children في React.Fragment ، لكن حالفني الحظ في القيام بذلك

return (children as React.ReactElement);

return <>{foo(}</>; طوال الليل. <> هو الحل.

هذا يسبب لي مشاكل أيضا.

TL ؛ DR:

لديّ HOC يضيف خاصيات إلى مكون معين ، وأنا أحاول استخدامه مع مكون وظيفي يحتوي على return children; . إنه يعمل فقط إذا استخدمت الحل البديل return <>{children}</>; .

المزيد من التفاصيل:

فيما يلي نسخة مبسطة من HOC:

export interface ExtraProps {
  extraProp1: string;
}

export const withExtraProps = <P extends object>(Component: React.ComponentType<P>) => {
  return class extends React.Component<Omit<P, keyof ExtraProps>> {
    render() {
      const extraProps = {
        extraProp1: 'test'
      };

      return (
        <Component {...this.props as P} {...extraProps} />
      )
    }
  }
}

فيما يلي نسخة مبسطة من المكون الوظيفي:

interface ComponentProps extends ExtraProps {
  children?: React.ReactNode;
  loadingComponent?: ReactElement;
}

export function ExampleComponent(props: ComponentProps) {
  const { children, loadingComponent } = props;

  const [loading, setLoading] = useState(false);

  useEffect(() => {
    const fetchData = async () => {
      setLoading(true);
      await someAsyncCall();
      setLoading(false);
    }

    fetchData();
  });

  if (loading) {
    return loadingComponent || null;
  }

  return children;
}

// This line errors:
export const FeatureFlag = withExtraProps(ExampleComponent);

أحصل على الخطأ التالية:

Argument of type '(props: ComponentProps) => {} | null | undefined' is not assignable to parameter of type 'ComponentType<ComponentProps>'.
  Type '(props: ComponentProps) => {} | null | undefined' is not assignable to type 'FunctionComponent<ComponentProps>'.
    Type '{} | null | undefined' is not assignable to type 'ReactElement<any, string | ((props: any) => ReactElement<any, string | ... | (new (props: any) => Component<any, any, any>)> | null) | (new (props: any) => Component<any, any, any>)> | null'.
      Type 'undefined' is not assignable to type 'ReactElement<any, string | ((props: any) => ReactElement<any, string | ... | (new (props: any) => Component<any, any, any>)> | null) | (new (props: any) => Component<any, any, any>)> | null'.

إذا قمت بإضافة نوع إرجاع ReactElement | null إلى ExampleComponent ، فإنه يتوقف عن الشكوى من تمريره إلى HOC ، ولكن لا يزال هناك أخطاء حيث أعيد الأطفال:

export function ExampleComponent(props: ComponentProps): ReactElement | null {
  ...
  ...
  return children; // Type 'ReactNode' is not assignable to type 'ReactElement<any, string | ((props: any) => ReactElement<any, string | ... | (new (props: any) => Component<any, any, any>)> | null) | (new (props: any) => Component<any, any, any>)> | null'.

}

كما هو الحال مع الآخرين هنا ، إذا قمت بتغييره إلى return <>{children}</>; ، فإنه يعمل ، لكنه يشعر بأنه إجمالي وغير ضروري.

لديّ _exact_ نفس المشكلة مثل kyrstenkelly - تم تمرير دالة HOC على React.FC مما يجعلها أطفالًا.

إصلاح <> children(...) </> يعمل ، لكن هل هناك حل أفضل حتى الآن؟

أيضا وجود هذه المشكلة! نقوم حاليًا بعمل الحل المقترح لحل التغليف باستخدام React.Fragment

كذلك هنا

interface IIntlMessageProps {
    id: string;
    valuesGiven?: {[key:string]:string};
}

// this doesn't work - -- TS2769 Type 'null' is not assignable to type '(nodes:ReactNodeARray) => ReactNode' | ... | undefined
export const IntlMessage: React.FC<IIntlMessageProps> = (props) => {
    return (
        <FormattedMessage id={props.id} values={props.valuesGiven}>
            {props.children}
        </FormattedMessage>
    )
};
//Nope -- TS2769 Type 'Element' is not assignable to type '(nodes:ReactNodeARray) => ReactNode'
export const IntlMessage: React.FC<IIntlMessageProps> = (props) => {
    return (
        <FormattedMessage id={props.id} values={props.valuesGiven}>
            <React.Fragment>{props.children}</React.Fragment>
        </FormattedMessage>
    )
};

// Nope -- TS2769 Type 'Element' is not assignable to type '(nodes:ReactNodeARray) => ReactNode'
export const IntlMessage: React.FC<IIntlMessageProps> | null = (props) => {
    return (
        <FormattedMessage id={props.id} values={props.valuesGiven}>
            <>{props.children}</>
        </FormattedMessage>
    )
};

// Nope -- TS2769 Type '{}' is not assignable to type '(nodes:ReactNodeARray) => ReactNode'
export const IntlMessage: React.FC<IIntlMessageProps> = (props) => {
    return (
        <FormattedMessage id={props.id} values={props.valuesGiven}>
            {props.children ? props.children : undefined}
        </FormattedMessage>
    )
};


أعتقد أنني جربت كل ما تم تقديمه هنا ... :( أي دليل؟

الحل هو أنك تحتاج إلى لفه في جزء.

import React from 'react'

const Something: React.FC = ({ children }) => (
 <> { children } </>
)

سيؤدي هذا إلى إصلاح الخطأ Type '({ children }: { children?: ReactNode; }) => ReactNode' is not assignable to type 'FunctionComponent .

إذا أمكن ، أود تجنب الأجزاء وجعل نظام نوع JSX يدعم نفس أنواع التركيبات التي يدعمها JavaScript و Flow React ، مما يساعد TypeScript على العمل بشكل أفضل مع أنماط مكتبة الجهات الخارجية.

هناك شيء آخر غير مثالي وجدته هو أن الأجزاء تعمق شجرة المكونات ، خاصة في مكونات المنفعة / الغلاف (حالة في نقطة: عنصر نائب للتفاعل). يبدو أن الإرسال إلى React.ReactElement أسلوب أفضل في هذا النوع من المكتبات ، لكنني أفضل عدم الحاجة إلى الإرسال.

لقد جربت طريقة لتغيير هذا النوع ، لكنني توقفت مع فحص نوع JSX باستخدام مكون وظيفي من النوع الجديد. لا يزال لدي الفرع ، كان من الممكن أن أقسم أنني قمت بعمل علاقات عامة لطلب المساعدة ، لا يمكنني العثور عليه مرة أخرى ...

حسنًا ، إذا احتاج النوع إلى عدم السماح بمصفوفات من العقد ، فهذا لا يعني أنه يجب أن يمنع ReactText ، ReactPortal ، boolean ، null ، و undefined وكذلك ما يفعله استخدام ReactElement .

ما الحكمة من منع هذه الأنواع الإضافية؟

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات