原文鏈接: https://medium.com/@jrwebdev/...
和之前的文章一樣,本文也要求你對render props有一些知識(shí)背景,如果沒有官方文檔可能會(huì)對你有很大的幫助。本文將會(huì)使用函數(shù)作為children的render props模式以及結(jié)合React的context API來作為例子。如果你想使用類似于render這樣子的render props,那也只需要把下面例子的children作為你要渲染的props即可。
為了展示render props,我們將要重寫之前文章的makeCounter HOC。這里先展示HOC的版本:
export interface InjectedCounterProps { value: number; onIncrement(): void; onDecrement(): void; } interface MakeCounterProps { minValue?: number; maxValue?: number; } interface MakeCounterState { value: number; } const makeCounter =( Component: React.ComponentType
) => class MakeCounter extends React.Component< Subtract
& MakeCounterProps, MakeCounterState > { state: MakeCounterState = { value: 0, }; increment = () => { this.setState(prevState => ({ value: prevState.value === this.props.maxValue ? prevState.value : prevState.value + 1, })); }; decrement = () => { this.setState(prevState => ({ value: prevState.value === this.props.minValue ? prevState.value : prevState.value - 1, })); }; render() { const { minValue, maxValue, ...props } = this.props; return (
); } };
HOC向組件注入了value和兩個(gè)回調(diào)函數(shù)(onIncrement 和 onDecrement),此外還在HOC內(nèi)部使用minValue和maxValue兩個(gè)props而沒有傳遞給組件。我們討論了如果組件需要知道這些值,如何不傳遞props可能會(huì)出現(xiàn)問題,并且如果使用多個(gè)HOC包裝組件,注入的props的命名也可能與其他HOC注入的props沖突。
makeCounter HOC將會(huì)被像下面這樣重寫:
interface InjectedCounterProps { value: number; onIncrement(): void; onDecrement(): void; } interface MakeCounterProps { minValue?: number; maxValue?: number; children(props: InjectedCounterProps): JSX.Element; } interface MakeCounterState { value: number; } class MakeCounter extends React.Component{ state: MakeCounterState = { value: 0, }; increment = () => { this.setState(prevState => ({ value: prevState.value === this.props.maxValue ? prevState.value : prevState.value + 1, })); }; decrement = () => { this.setState(prevState => ({ value: prevState.value === this.props.minValue ? prevState.value : prevState.value - 1, })); }; render() { return this.props.children({ value: this.state.value, onIncrement: this.increment, onDecrement: this.decrement, }); } }
這里有一些需要注意的變化。首先,injectedCounterProps被保留,因?yàn)槲覀冃枰x一個(gè)props的interface在render props函數(shù)調(diào)用上而不是傳遞給組件的props(和HOC一樣)。MakeCounter(MakeCounterProps)的props已經(jīng)改變,加上以下內(nèi)容:
children(props: InjectedCounterProps): JSX.Element;
這是render prop,然后組件內(nèi)需要一個(gè)函數(shù)帶上注入的props并返回JSX element。下面是它用來突出顯示這一點(diǎn)的示例:
interface CounterProps { style: React.CSSProperties; minValue?: number; maxValue?: number; } const Counter = (props: CounterProps) => ({injectedProps => ( );{injectedProps.value})}
MakeCounter自己的組件聲明變得簡單多了;它不再被包裝在函數(shù)中,因?yàn)樗辉偈桥R時(shí)的,輸入也更加簡單,不需要泛型、做差值和類型的交集。它只有簡單的MakeCounterProps和MakeCounterState,就像其他任何組成部分一樣:
class MakeCounter extends React.Component< MakeCounterProps, MakeCounterState >
最后,render()的工作也變少了;它只是一個(gè)函數(shù)調(diào)用并帶上注入的props-不需要破壞和對象的props擴(kuò)展運(yùn)算符展開了!
return this.props.children({ value: this.state.value, onIncrement: this.increment, onDecrement: this.decrement, });
然后,render prop組件允許對props的命名和在使用的靈活性上進(jìn)行更多的控制,這是和HOC等效的一個(gè)問題:
interface CounterProps { style: React.CSSProperties; value: number; minCounterValue?: number; maxCounterValue?: number; } const Counter = (props: CounterProps) => ({injectedProps => ( );)}Some other value: {props.value}{injectedProps.value}{props.minCounterValue !== undefined ? (Min value: {props.minCounterValue}) : null} {props.maxCounterValue !== undefined ? (Max value: {props.maxCounterValue}) : null}
有了所有這些好處,特別是更簡單的輸入,那么為什么不一直使用render props呢?當(dāng)然可以,這樣做不會(huì)有任何問題,但要注意render props組件的一些問題。
首先,這里有一個(gè)關(guān)注點(diǎn)以外的問題;MakeCounter組件現(xiàn)在被放在了Counter組件內(nèi)而不是包裝了它,這使得隔離測試這兩個(gè)組件更加困難。其次,由于props被注入到組件的渲染函數(shù)中,因此不能在生命周期方法中使用它們(前提是計(jì)數(shù)器被更改為類組件)。
這兩個(gè)問題都很容易解決,因?yàn)槟梢允褂胷ender props組件簡單地生成一個(gè)新組件:
interface CounterProps extends InjectedCounterProps { style: React.CSSProperties; } const Counter = (props: CounterProps) => ({props.value}); interface WrappedCounterProps extends CounterProps { minValue?: number; maxValue?: number; } const WrappedCounter = ({ minValue, maxValue, ...props }: WrappedCounterProps) => ({injectedProps => );}
另一個(gè)問題是,一般來說,它不太方便,現(xiàn)在使用者需要編寫很多樣板文件,特別是如果他們只想將組件包裝在一個(gè)多帶帶的臨時(shí)文件中并按原樣使用props。這可以通過從render props組件生成HOC來補(bǔ)救:
import { Subtract, Omit } from "utility-types"; import MakeCounter, { MakeCounterProps, InjectedCounterProps } from "./MakeCounter"; type MakeCounterHocProps = Omit; const makeCounter = ( Component: React.ComponentType
): React.SFC
& MakeCounterHocProps> => ({ minValue, maxValue, ...props }: MakeCounterHocProps) => ( {injectedProps => );}
在這里,上一篇文章的技術(shù),以及render props組件的現(xiàn)有類型,被用來生成HOC。這里唯一需要注意的是,我們必須從HOC的props中移除render prop(children),以便在使用時(shí)不暴露它:
type MakeCounterHocProps = Omit;
最后,HOC和render props組件之間的權(quán)衡歸結(jié)為靈活性和便利性。這可以通過首先編寫render props組件,然后從中生成HOC來解決,這使使用者能夠在兩者之間進(jìn)行選擇。這種方法在可重用組件庫中越來越常見,例如優(yōu)秀的render-fns庫。
就TypeScript而言,毫無疑問,hocs的類型定義要困難得多;盡管通過這兩篇文章中的示例,它表明這種負(fù)擔(dān)是由HOC的提供者而不是使用者承擔(dān)的。在使用方面,可以認(rèn)為使用HOC比使用render props組件更容易。
在react v16.8.0之前,我建議使用render props組件以提高鍵入的靈活性和簡單性,如果需要,例如構(gòu)建可重用的組件庫,或者對于簡單在項(xiàng)目中使用的render props組件,我將僅從中生成HOC。在react v16.8.0中釋放react hook之后,我強(qiáng)烈建議在可能的情況下對兩個(gè)高階組件或render props使用它們,因?yàn)樗鼈兊念愋透唵巍?/p>
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/103646.html
摘要:原文鏈接高階組件在中是組件復(fù)用的一個(gè)強(qiáng)大工具。在本文中,高階組件將會(huì)被分為兩種基本模式,我們將其命名為和用附加的功能來包裹組件。這里我們使用泛型表示傳遞到的組件的。在這里,我們定義從返回的組件,并指定該組件將包括傳入組件的和的。 原文鏈接:https://medium.com/@jrwebdev/... 高階組件(HOCs)在React中是組件復(fù)用的一個(gè)強(qiáng)大工具。但是,經(jīng)常有開發(fā)者在...
摘要:致力于為應(yīng)用提供一個(gè)類型安全表達(dá)力強(qiáng)可組合的狀態(tài)管理方案。是一組的命名空間。是內(nèi)置組件的鏡像,但允許組件的額外接受類型的數(shù)據(jù)。這次內(nèi)容更新,是由組件處理的。這些小的組件不必知道所有的應(yīng)用狀態(tài)數(shù)據(jù)。這是因?yàn)榇蟛糠謱Φ难芯縼碜杂凇? Focal Focal 致力于為 React 應(yīng)用提供一個(gè)類型安全、表達(dá)力強(qiáng)、可組合的狀態(tài)管理方案。 用一個(gè)不可變的 (immutable) 、響應(yīng)式的 (o...
摘要:現(xiàn)已存在許多成熟的狀態(tài)管理解決方案,還有基于的但對于我個(gè)人來說,理想的狀態(tài)管理工具只需同時(shí)滿足兩個(gè)特點(diǎn)簡單易用,并且適合中大型項(xiàng)目完美地支持要做到這兩點(diǎn)其實(shí)并不簡單。所以我決定自己造一個(gè)可能是基于和最好的狀態(tài)管理工具 現(xiàn)已存在許多成熟的狀態(tài)管理解決方案:Redux、Mobx、Mobx-state-tree,還有基于 Redux 的 Dva.js、Rematch... 但對于我個(gè)人來說,...
摘要:近兩年來一直在關(guān)注開發(fā),最近也開始全面應(yīng)用。首先,我們從無狀態(tài)組件開始。渲染回調(diào)模式有一種重用組件邏輯的設(shè)計(jì)方式是把組件的寫成渲染回調(diào)函數(shù)或者暴露一個(gè)函數(shù)屬性出來。最后,我們將這個(gè)回調(diào)函數(shù)的參數(shù)聲明為一個(gè)獨(dú)立的類型。 近兩年來一直在關(guān)注 React 開發(fā),最近也開始全面應(yīng)用 TypeScript 。國內(nèi)有很多講解 React 和 TypeScript 的教程,但如何將 TypeScri...
閱讀 1021·2021-10-27 14:15
閱讀 2775·2021-10-25 09:45
閱讀 1941·2021-09-02 09:45
閱讀 3367·2019-08-30 15:55
閱讀 1807·2019-08-29 16:05
閱讀 3203·2019-08-28 18:13
閱讀 3117·2019-08-26 13:58
閱讀 455·2019-08-26 12:01