您好,登錄后才能下訂單哦!
這篇文章主要介紹了怎么使用TypeScript開發React函數式組件的相關知識,內容詳細易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇怎么使用TypeScript開發React函數式組件文章都會有所收獲,下面我們一起來看看吧。
在我們使用 React 開發項目時,使用最多的應該都是組件,組件又分為函數組件和類組件,我們可以這么定義:
定義函數組件:
function Welcome(props) { return <h2>Hello, {props.name}</h2>; }
定義類組件:
class Welcome extends React.Component { render() { return <h2>Hello, {this.props.name}</h2>; } }
這篇文章我會和大家介紹使用 TypeScript 定義函數式組件的 4 種方法,還有幾個使用過程中需要注意的問題。
函數式組件通常接受一個 props
參數,返回一個 JSX 元素或者 null
。
當我們需要使用 TypeScript 去定義一個函數式組件時,我們有 4 種方式,4 種方式各有各的優缺點,看具體情況使用。
由于 React 不是使用 TypeScript 開發的,使用的是社區開發的 @type/react
包提供的類型,里面有一個通用類型 FC
,允許我們為函數組件添加類型。
type FCProps = { text: string }; // React.FunctionComponent 的簡寫 const FCComponent: React.FC<FCProps> = ({ text = "" }) => <div>{text}</div>;
這里的 React.FC
是 React.FunctionComponent
的簡寫。
當組件包含子元素,TypeScript 會提示警告:
type FCProps = { text: string }; const FCComponent: React.FC<FCProps> = ({ text = "" }) => <div>{text}</div>; function App() { return ( <div className="App"> <FCComponent text="Hello Chris1993."> <span>children</span> </FCComponent> </div> ); }
提示警告內容:
Type '{ children: string; text: string; }' is not assignable to type 'IntrinsicAttributes & FCProps'. Property 'children' does not exist on type 'IntrinsicAttributes & FCProps'.
使用 JSX.Element
類型作為函數式組件的返回值類型,當組件的返回值不是 JSX.Element
類型時,TypeScript 就會提示錯誤。
type FCProps = { text: string }; const ElementComponent = ({ text }: FCProps): JSX.Element => <div>{text}</div>; function App() { return ( <div className="App"> <ElementComponent text="Hello Chris1993."></ElementComponent> </div> ); }
由于 React
組件包含子元素時,會隱式傳遞一個 children
屬性,導致定義的參數類型出錯,因此我們可以直接定義一個完整的參數接口,包含了 children
屬性的類型:
type FCProps = { text: string; children?: any }; const FCComponent: React.FC<FCProps> = ({ text = "" }) => <div>{text}</div>; function App() { return ( <div className="App"> <FCComponent text="Hello Chris1993."> <span>children</span> </FCComponent> </div> ); }
第 3 種方法每次都要手動寫一個 children
屬性類型比較麻煩,這時候我們就可以使用 React.PropsWithChildren
類型,它本身封裝了 children
的類型聲明:
// react/index.d.ts type PropsWithChildren<P> = P & { children?: ReactNode };
因此,使用 React.PropsWithChildren
類型定義函數式組件,就不用去處理 children
的類型了:
type IProps = React.PropsWithChildren<{ text: string }>; const PropsComponent = ({ text }: IProps) => <div>{text}</div>; function App() { return ( <div className="App"> <PropsComponent text="Hello Chris1993."> <span>children</span> </PropsComponent> </div> ); }
當我們在函數式組件內使用條件語句時,如果返回的是非 JSX 元素或者非 null 的值,React 將會報錯:
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> ); }
正確的處理方式,應該是讓函數式組件返回一個有效的 JSX 元素或者 null:
const ConditionComponent = ({ useRender = false }) => useRender ? <span>Render ConditionComponent</span> : <span>error</span>;// ? // or const ConditionComponent = ({ useRender = false }) => useRender ? <span>Render ConditionComponent</span> : null;// ?
當然你也不能這樣寫,當屬性 useRender
為 true
時,也會出錯:
const ConditionComponent = ({ useRender = false }) => useRender && <span>Render ConditionComponent</span>;// ?
當我們的組件直接返回 Array.fill()
的結果時,TypeScript 會提示錯誤。
const ArrayComponent = () => Array(3).fill(<span>Chris1993</span>); // ? function App() { return ( <div className="App"> <ArrayComponent></ArrayComponent> </div> ); }
提示下面內容:
'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
為了解決這個問題,我們可以定義函數的返回值類型:
const ArrayComponent = () => Array(3).fill(<span>Chris1993</span>) as any as JSX.Element; // ?
在使用 TypeScript 開發 React 函數式組件的時候,也可以使用泛型進行約束,聲明一個泛型組件(Generic Components),這樣可以讓我們的組件更加靈活。
可以這樣使用:
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> ); }
在 Generic Components 章節中介紹到更高級的使用方式:
interface Props<T> { items: T[]; renderItem: (item: T) => React.ReactNode; } const List = <T extends unknown>(props: Props<T>) => { const { items, renderItem } = props; const [state, setState] = React.useState<T[]>([]); // You can use type T in List function scope. return ( <div> {items.map(renderItem)} <button onClick={() => setState(items)}>Clone</button> {JSON.stringify(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'. */} {item.toPrecision(3)} </li> )} /> </div> ); }
關于“怎么使用TypeScript開發React函數式組件”這篇文章的內容就介紹到這里,感謝各位的閱讀!相信大家對“怎么使用TypeScript開發React函數式組件”知識都有一定的了解,大家如果還想學習更多知識,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。