javascript - React 18 TypeScript çocuklar FC


React 18'e yükselttim ve her şey sorunsuz bir şekilde derlendi. Bugün, children kullanan her bileşenin bir hata verdiği görünüyor. Property 'children' does not exist on type 'IPageProps'.

Çocuk propsları önceden FC arayüzüne otomatik olarak dahildi. Şimdi ise anlaşılan children: ReactNode öğesini manuel olarak eklemem gerekiyor. React çocukları için doğru TypeScript tipi nedir?

Bu React 18 güncellemesinin bir parçası mı, yoksa ortamımda bir şey mi yanlış?

package.json

"react": "^18.0.0",
"react-dom": "^18.0.0",
"next": "12.1.4",
"@types/react": "18.0.0",
"@types/react-dom": "18.0.0",

tsconfig.json

{
  "compilerOptions": {
    "target": "esnext",
    "lib": ["dom", "dom.iterable", "esnext"],
    "allowJs": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "preserve",
    "alwaysStrict": true,
    "sourceMap": true,
    "incremental": true
  },
  "include": ["src"],
  "exclude": ["node_modules"]
}

Cevap #1

Bu cevap doğru olsa da, kesinlikle bu PropsWithChildren yardımcısını kullanmak zorunda olmadığınızı belirtmek isterim. (Bu, öncelikle codemod için faydalıdır, manuel kullanım için değil.)

Bunun yerine, onları manuel olarak tanımlamayı daha kolay buluyorum.

Önce

import * as React from 'react';

type Props = {};
const Component: React.FC<Props> = ({children}) => {...}

Sonra

import * as React from 'react';

type Props = {
  children?: React.ReactNode
};
const Component: React.FC<Props> = ({children}) => {...}

İhtiyaç duyulan tek şey bu.

Veya tamamen React.FC kullanımını bırakabilirsiniz.

import * as React from 'react';

type Props = {
  children?: React.ReactNode
};

function Component({children}: Props): React.ReactNode {
  ...
}

React'ta, children normal bir prop'tur ve özel bir şey değildir. Bu yüzden onu diğer tüm prop'ları tanımladığınız gibi tanımlamanız gerekir. Önceki bunu gizleyen tip tanımlamaları yanlıştı.

Cevap #2

Nasıl çözülür

Sahne gereçleri yok

Önce

import React from 'react';

const Component: React.FC = ({children}) => {...}

Sonra

Yardımcı tipinizi tanımlamak için örn. react.d.ts oluşturun 1

import React from 'react';

export type ReactFCWithChildren = React.FC<PropsWithChildren>;
import {ReactFCWithChildren } from './react';

const Component: ReactFCWithChildren = ({children}) => {...}

veya

import React from 'react';

const Component: React.FC<React.PropsWithChildren> = ({children}) => {...}

Tebrikler

Önce

import React from 'react';

interface Props {
  ...
}
const Component: React.FC<Props> = ({children}) => {...}

Sonra

import React from 'react';

interface Props {
  ...
}
const Component: React.FC<React.PropsWithChildren<Props>> = ({children}) => {...}

veya

import React from 'react';

interface Props extends React.PropsWithChildren {
  ...
}

const Component: React.FC<Props> = ({children}) => {...}

1 children'ı manuel olarak tanımlamak kolay görünse de, @types paketinde sizin için zaten hazırlanmış türlerden yararlanmak daha iyidir. Gelecekte türde değişiklikler olduğunda, bu değişiklik kütüphaneden kodunuzun her yerine otomatik olarak yayıldığından, kendiniz dokunmak zorunda kalmazsınız.

Herhangi bir nedenle uyarıları bastır

Aşağıdaki tanımı içeren bir react.d.ts dosyası oluşturarak react tiplerini geçersiz kılabilir ve tipi @types/react v17’ye geri döndürebilirsiniz

import * as React from '@types/react';

declare module 'react' {
  interface FunctionComponent<P = {}> {
    (props: PropsWithChildren<P>, context?: any): ReactElement<any, any> | null;
  }
}

FC imzası neden değişti

children özelliği React.FunctionComponent (React.FC)'den kaldırıldı, bu yüzden bunu açıkça tanımlamanız gerekiyor.

TS size şu tür hataları söyleyecek

‘{ children: ...; }’ türünün ‘IntrinsicAttributes’ türü ile ortak hiçbir özelliği yok.

Bunu nedenini burada okuyabilirsiniz. Özetle bu, şu tür hataları önler

const ComponentWithNoChildren: React.FC = () => <>Hello</>;

...

<ComponentWithNoChildren>
   // passing children is wrong since component does not accept any
   <UnusedChildrenSinceComponentHasNoChildren /> 
</ComponentWithNoChildren>

Cevap #3

Evet, React.FC türü değişti. Ama kendi türünüzü blackjack ve React çocuklarıyla tanımlayabilirsiniz.

Benim yöntemim, içerik olarak şöyle bir şeyle src/types/react.d.ts dosyası yaratmaktır:

import React, { PropsWithChildren } from 'react';

export type ReactFCC<T> = React.FC<PropsWithChildren<T>>;

Güncelleme #01

T parametresi için varsayılan değer ekleyebilirsiniz:

import React, { PropsWithChildren } from 'react';

export type ReactFCC<T = Record<string, unknown>> = React.FC<PropsWithChildren<T>>;

veya

import React, { PropsWithChildren } from 'react';

export type ReactFCC<T = unknown> = React.FC<PropsWithChildren<T>>;

Artık uyarı olmadan bir ReactFCC generiğinde tür belirtmemeyi seçebilirsiniz.

Önce :

export const Component: ReactFCC<SomeType> = props => {

  const { children } = props;
  
  /* ... */
}

Sonra :

export const Component: ReactFCC = props => {

  const { children } = props;
  
  /* ... */
}

İlgili makaleler