[英]Implement INTERFACE based functionality in reactjs to render component based on variable
如何使用基於界面的功能來基於選項卡選擇呈現組件。
假設我有 3 個組件,即
我想要某種功能,其中所有這些組件都實現接口InterfaceBasedComponent
例如
OneTimeOnlyScheduleComponent implements InterfaceBasedComponent
DailyScheduleComponent implements InterfaceBasedComponent
WeeklyScheduleComponent implements InterfaceBasedComponent
在 ReactJS 中,我應該能夠使用工廠模式或其他方式創建 object。
{/* TAB BUTTONS */}
<ul className="nav nav-tabs border-bottom-0" role="tablist">
{
freqType.map(freq => {
return (
![64, 128].includes(freq.key) &&
<li key={freq.key} className="nav-item">
<a href="#freqType1" property_name="freq_type"
className={"nav-link " + (state.freq_type === freq.key ? 'active' : '')}
onClick={(e) => scheduleTypeChange(freq.key)}
data-toggle="tab" role="tab"
aria-controls="freqType1"
aria-selected={state.freq_type === freq.key}>
{freq.value}</a>
</li>)
})
}
</ul>
根據上面的代碼,當用戶單擊其中一個選項卡時,應該會生成相應的組件。
<div className="tab-content border">
{/* One time schedule */}
<div className={"m-2 tab-pane fade " + (state.freq_type === 1 ? showClass : hiddenClass)} id="freqType1" role="tabpanel">
<OneTimeOnlyScheduleComponent schedule={state} onComponentChange={commonScheduleChangeHandler} />
</div>
{/* Daily schedule */}
<div className={"m-2 tab-pane fade " + (state.freq_type === 4 ? showClass : hiddenClass)} id="freqType4" role="tabpanel">
<DailyScheduleComponent schedule={state} onComponentChange={commonScheduleChangeHandler} />
</div>
{/* Weekly schedule */}
< div className={"m-2 tab-pane fade " + (state.freq_type === 8 ? showClass : hiddenClass)} id="freqType8" role="tabpanel">
<WeeklyScheduleComponent schedule={state} onComponentChange={commonScheduleChangeHandler} />
</div>
{/* Monthly schedule */}
< div className={"m-2 tab-pane fade " + (state.freq_type === 16 ? showClass : hiddenClass)} id="freqType16" role="tabpanel">
<MonthlyScheduleComponent schedule={state} onComponentChange={commonScheduleChangeHandler} />
</div>
{/* Monthly relative schedule */}
<div className={"m-2 tab-pane fade " + (state.freq_type === 32 ? showClass : hiddenClass)} id="freqType32" role="tabpanel">
<MonthlyRelativeScheduleComponent schedule={state} onComponentChange={commonScheduleChangeHandler} />
</div>
{/* Yearly schedule */}
<div className={"m-2 tab-pane fade " + (state.freq_type === 64 ? showClass : hiddenClass)} id="freqType64" role="tabpanel">
<YearlyScheduleComponent schedule={state} onComponentChange={commonScheduleChangeHandler} />
</div>
{/* Year long schedule */}
<div className={"m-2 tab-pane fade " + (state.freq_type === 128 ? showClass : hiddenClass)} id="freqType128" role="tabpanel">
<YearLongScheduleComponent schedule={state} onComponentChange={commonScheduleChangeHandler} />
</div>
</div>
理想情況下,我希望簡化代碼以使用基於接口的 object 渲染,例如InterfaceBasedComponent
。 該接口應該能夠創建所需組件的 object。
<div className="tab-content border">
{
freqType.map(freq => {
return (
![64, 128].includes(freq.key) &&
<div className={"m-2 tab-pane fade " + (state.freq_type === freq.key ? showClass : hiddenClass)}
id={"freqType" + freq.key}
role="tabpanel">
<InterfaceBasedComponent schedule={state} onComponentChange={commonScheduleChangeHandler} />
</div>
)}
}
</div >
你說:
我應該能夠使用工廠模式創建 object... 我希望簡化代碼以使用基於接口的 object 渲染
但是您實際上想要簡化什么? (例如,工廠不是接口)。
如果您明確想要使用接口,那么這是不可能的,因為 Javascript 沒有接口,因此沒有 React。
( Typscript 中有接口,但我確定這不是你的意思)
但是您可以很好地使用工廠 function 來創建組件:
const OneTimeOnlyScheduleComponent = ( props ) => {
return <>
<p>( specific stuff to OneTimeOnlyScheduleComponent )</p>
{ props.children }
</>;
};
const DailyScheduleComponent = ( props ) => {
return <>
<p>( specific stuff to DailyScheduleComponent )</p>
{ props.children }
</>;
};
export const ListFactory = ( props: IProps ) => {
const { schedule } = props;
const List = <ul>
{ schedule.list.map( item => <li key={ item.key }>{ item.value }</li> ) }
</ul>;
switch( schedule.type ){
case 'onetime': return <OneTimeOnlyScheduleComponent>{ List }</OneTimeOnlyScheduleComponent>;
case 'daily': return <DailyScheduleComponent>{ List }</DailyScheduleComponent>;
default:
return 'error';
}
};
function App(){
const [ schedule, setSchedule ] = useState( { type: 'onetime', list: list } );
return <div>
<button onClick={ () => { setSchedule( { type: 'daily', list: list } ); }}>
switch
</button>
<ListFactory schedule={ schedule } />
</div>;
}
React 中還有高階組件(HOC) ,從某種意義上說,它可能解決的問題更像接口會做什么......但我不明白在這種情況下這會對你有什么幫助。
例如,您可能有一個名為implementsList
的 HOC,但是您的所有組件確實應該實現該列表,因此您不會使用這種方法擺脫代碼重復:
export const OneTimeOnlyScheduleComponent = implementsList(( props ) => {
return <><p>( specific stuff to OneTimeOnlyScheduleComponent )</p>
<ul>
{ props.list.map( item => <li key={ item.key }>{ item.value }</li> ) }
</ul>
</>;
});
export const DailyScheduleComponent = implementsList(( props ) => {
return <><p>( specific stuff to DailyScheduleComponent )</p>
<ul>
{ props.list.map( item => <li key={ item.key }>{ item.value }</li> ) }
</ul>
</>;
});
function implementsList(WrappedComponent) {
return function( props ){
return <>
<p>type: { props.schedule.type }</p>
<WrappedComponent list={ props.schedule.list } />
</>;
};
}
順便說一句:按照慣例,HOC 應該以前綴with...
命名,因此在這種情況下,HOC 最好命名為withList
,這也更好地代表了使用 HOC 的意圖。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.