Preface
When we use React development projects, the most used components should be the components, and the components are divided intoFunction ComponentsandClass Components, we can define it like this:
Define function components:
function Welcome(props) { return <h1>Hello, {}</h1>; }
Define class components:
class Welcome extends { render() { return <h1>Hello, {}</h1>; } }
In this article, I will introduce to you four methods to use TypeScript to define functional components, and there are several issues that need to be paid attention to during use.
How to define functional components using TypeScript
Functional components usually accept oneprops
Parameter, return a JSX element ornull
。
When we need to use TypeScript to define a functional component, we have 4 methods, and the 4 methods have their own advantages and disadvantages, depending on the specific situation.
1. Use
Since React is not developed using TypeScript, it is developed by the community.@type/react
The type provided by the package has a common type.FC
, allows us to add types to function components.
type FCProps = { text: string }; // Abbreviationconst FCComponent: <FCProps> = ({ text = "" }) => <div>{text}</div>;
Hereyes
abbreviation of .
When the component contains child elements, TypeScript will prompt a warning:
type FCProps = { text: string }; const FCComponent: <FCProps> = ({ text = "" }) => <div>{text}</div>; function App() { return ( <div className="App"> <FCComponent text="Hello Chris1993."> <span>children</span> </FCComponent> </div> ); }
Prompt warning content:
Type '{ children: string; text: string; }' is not assignable to type 'IntrinsicAttributes & FCProps'. Property 'children' does not exist on type 'IntrinsicAttributes & FCProps'.
This is not recommended now. For details, please refer to these two links:
- Remove from Typescript template #8177;
- 《TypeScript + React: Why I don't use 》。
2. Use
useType is the return value type of the functional component, when the return value of the component is not
TypeScript will prompt an error when typed.
type FCProps = { text: string }; const ElementComponent = ({ text }: FCProps): => <div>{text}</div>; function App() { return ( <div className="App"> <ElementComponent text="Hello Chris1993."></ElementComponent> </div> ); }
3. Directly define the complete type
becauseReact
When a component contains child elements, an implicitly passeschildren
Attributes, resulting in errors in the defined parameter type, so we can directly define a complete parameter interface, includingchildren
Type of attribute:
type FCProps = { text: string; children?: any }; const FCComponent: <FCProps> = ({ text = "" }) => <div>{text}</div>; function App() { return ( <div className="App"> <FCComponent text="Hello Chris1993."> <span>children</span> </FCComponent> </div> ); }
4. Use
The third method must be written manually every timechildren
Attribute type is more troublesome, we can use it at this timeType, it encapsulates itself
children
Type declaration:
// react/ type PropsWithChildren<P> = P & { children?: ReactNode };
Therefore, useThe type defines functional components, so you don't need to deal with it.
children
Type:
type IProps = <{ text: string }>; const PropsComponent = ({ text }: IProps) => <div>{text}</div>; function App() { return ( <div className="App"> <PropsComponent text="Hello Chris1993."> <span>children</span> </PropsComponent> </div> ); }
Things to note during use
1. The return value of the functional component cannot be a boolean value
When we use it in a functional componentConditional statementsWhen returned, if the value is a non-JSX element or a non-null value, React will report an error:
const ConditionComponent = ({ useRender = false }) => useRender ? <span>Render ConditionComponent</span> : false;// ❌ function App() { return ( <div className="App"> <ConditionComponent useRender></ConditionComponent> {/* 'ConditionComponent' cannot be used as a JSX component. Its return type 'false | Element' is not a valid JSX element. Type 'boolean' is not assignable to type 'ReactElement<any, any>'. */} </div> ); }
The correct way to deal with it is to have the functional component return a valid JSX element or null:
const ConditionComponent = ({ useRender = false }) => useRender ? <span>Render ConditionComponent</span> : <span>error</span>;// ✅ // or const ConditionComponent = ({ useRender = false }) => useRender ? <span>Render ConditionComponent</span> : null;// ✅
Of course you can't write this way, as attributesuseRender
fortrue
When , an error will also occur:
const ConditionComponent = ({ useRender = false }) => useRender && <span>Render ConditionComponent</span>;// ❌
2. Unable to use () for component fill
When our component returns directly()
When the result is, TypeScript will prompt an error.
const ArrayComponent = () => Array(3).fill(<span>Chris1993</span>); // ❌ function App() { return ( <div className="App"> <ArrayComponent></ArrayComponent> </div> ); }
Prompt the following:
'ArrayComponent' cannot be used as a JSX component. Its return type 'any[]' is not a valid JSX element. Type 'any[]' is missing the following properties from type 'ReactElement<any, any>': type, props, key
To solve this problem, we can define the return value type of the function:
const ArrayComponent = () => Array(3).fill(<span>Chris1993</span>) as any as ; // ✅
3. Support the use of generics to create components
When developing React functional components using TypeScript, you can also use generics to constrain and declare a generic component (Generic Components), which can make our components more flexible.
Can be used like this:
interface GenericProps<T> { content: T; } const GenericComponent = <T extends unknown>(props: GenericProps<T>) => { const { content } = props; const component = <>{content}</>; return <div>{component}</div>; }; function App() { return ( <div className="App"> { /* Success ✅ */} <GenericComponent<number> content={10} /> { /* Error ❌ Type 'string' is not assignable to type 'number'. */} <GenericComponent<number> content={"10"} /> </div> ); }
existGeneric Components The chapter introduces more advanced usage methods:
interface Props<T> { items: T[]; renderItem: (item: T) => ; } const List = <T extends unknown>(props: Props<T>) => { const { items, renderItem } = props; const [state, setState] = <T[]>([]); // You can use type T in List function scope. return ( <div> {(renderItem)} <button onClick={() => setState(items)}>Clone</button> {(state, null, 2)} </div> ); }; function App() { return ( <div className="App"> <List<number> items={[1, 2]} // type of 'string' inferred renderItem={(item) => ( <li key={item}> {/* Error: Property 'toPrecision' does not exist on type 'string'. */} {(3)} </li> )} /> </div> ); }
This is the article about using TypeScript to develop React functional components. For more related TypeScript development React content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!