@types/react
ν¨ν€μ§λ₯Ό μ¬μ©ν΄ 보μλλ° λ¬Έμ κ° μμμ΅λλ€.Definitions by:
in index.d.ts
μ°Έμ‘°) λλ΅νλ€.λ€μ κ΅¬μ± μμ
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'.
Element
μ children
λννλ©΄ μλν©λλ€.
children
λ₯Ό λ°ννλ κ²μ context
μ 무μΈκ°λ₯Ό μΆκ°νλ Provider κ΅¬μ± μμλ₯Ό λ§λ€ λ λ§€μ° μΌλ°μ μ
λλ€.
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μμ μ¬λ¬ μμλ₯Ό λ°νν μ μμ΅λλ€. μ΄λμ κ° νμλλΌλ μλ§ μ΄λ»κ²λ νλμ μΊ‘μν λμ΄ μμ κ²μ
λλ€.
Fiberκ° μλ React 16μμλ§ κ°λ₯ν©λλ€. :)
κ·Έλ€μ΄ λ°μ λμμ λ³κ²½νλμ§ νμ€νμ§ μμ§λ§ redux / react μμ±μλ https://egghead.io/lessons/ μμ λ³Ό μ μλ―μ΄ μμ λνΌλ₯Ό μμ±νκΈ° μν΄ this.props.childrenμ λ°ννλ κΈ°λ₯μ 보μ¬μ£Όμμ΅λλ€(μμμ childContextλ₯Ό μΆκ°νκΈ° μν΄μλ§).
react-nativeλ₯Ό μ¬μ©νλ©΄ λ λλ§μμ JSX μμμ λ°°μ΄μ λ°νν μ μμ΅λλ€. ν΄κ²° λ°©λ²μ this.props.children
λ₯Ό React.Children.only(this.props.children)
λ‘ λννλ κ²μ΄λ©° 루νΈλ‘ μμκ° λ μ΄μ μμΌλ©΄ throwλ©λλ€.
λ€, React.Children.only
λ₯Ό μ¬μ©ν μ μμ§λ§ ReactNode
μ ReactElement
λ λͺ¨λ this.props.children
μ μ ν¨ν κ°μ
λλ€.
const Title = props => <h1>{props.children}</h1>;
<Title>Woah</Title>
μ ν¨νκ³ ν©λ¦¬μ μΈ React μ½λμ λλ€.
λ°μ 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μ μ λ ₯ν μ μμ΅λλ€.
μ΄ λ¬Έμ λ₯Ό ν΄κ²°νκΈ° μν΄ νμ¬ children
λ₯Ό React.Fragment
μ λννκ³ μμ΅λλ€.
μ λ°μ΄νΈκ° μμ΅λκΉ?
μ΄κ²μ΄ children
λ₯Ό React.Fragment
μ λννλ κ²λ³΄λ€ λ€μ μ ννμ§ νμ€νμ§ μμ§λ§ μ΄μ΄ μ’μμ΅λλ€.
return (children as React.ReactElement);
return <>{foo(}</>;
λ°€μλλ‘. <>
λ ν΄κ²° λ°©λ²μ
λλ€.
μ΄κ²μ λμκ²λ λ¬Έμ λ₯Ό μΌμΌν€κ³ μμ΅λλ€.
μ£Όμ΄μ§ κ΅¬μ± μμμ μνμ μΆκ°νλ 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'.
ExampleComponentμ ReactElement | null
μ λ°ν μ νμ μΆκ°νλ©΄ 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}</>;
λ‘ λ³κ²½νλ©΄ μλνμ§λ§ κ±°μΉ κ³ λΆνμνκ² λκ»΄μ§λλ€.
@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κ° νμ¬ λΌμ΄λΈλ¬λ¦¬ ν¨ν΄κ³Ό λ μ μλνλλ‘ νκ³ μΆμ΅λλ€.
λ΄κ° μ°Ύμ λ λ€λ₯Έ λΉμ΄μμ μΈ κ²μ μ‘°κ°μ΄ κ΅¬μ± μμ νΈλ¦¬, νΉν μ νΈλ¦¬ν°/λνΌ κ΅¬μ± μμ(case-in-point: react-placeholder)μμ μ¬νλλ€λ κ²μ
λλ€. React.ReactElement
λ‘ μΊμ€ν
νλ κ²μ΄ μ΄λ¬ν μ’
λ₯μ λΌμ΄λΈλ¬λ¦¬μμ λ λμ μ κ·Ό λ°©μμ²λΌ 보μ΄μ§λ§ μΊμ€ν
ν νμκ° μμ΅λλ€.
ν΄λΉ μ νμ λ³κ²½νκΈ° μν μ κ·Ό λ°©μμ μλνμ§λ§ μλ‘μ΄ μ νμ κΈ°λ₯ κ΅¬μ± μμλ₯Ό μ¬μ©νμ¬ JSX μ ν κ²μ¬μ κ°νκ² λμμ΅λλ€. μμ§ μ§μ μ΄ μκ³ , λμμ μμ²νλ PRμ νλ€κ³ λ§ΉμΈν μ μμμ§λ§ λ€μ μ°Ύμ μ μμ΅λλ€...
μ’μ΅λλ€. μ νμ΄ λ
Έλ λ°°μ΄μ νμ©νμ§ μμμΌ νλ κ²½μ° ReactText
, ReactPortal
, boolean
, null
λ° undefined
λ₯Ό νμ©νμ§ μμμΌ νλ€λ μλ―Έλ μλλλ€. ReactElement
μ μ¬μ©λ².
μ΄λ¬ν μΆκ° μ νμ κΈμ§νλ μ΄μ λ 무μμ λκΉ?
κ°μ₯ μ μ©ν λκΈ
μ΄ λ¬Έμ λ₯Ό ν΄κ²°νκΈ° μν΄ νμ¬
children
λ₯ΌReact.Fragment
μ λννκ³ μμ΅λλ€.