[英]React conditional render pattern
我已經實現了一個模態組件,在屏幕上顯示模式對話框。 通常,模態將有條件地顯示。 我可以通過兩種方式在render函數中執行此操作:
render(){
...
<Modal show={this.state.showModal}>
// something in modal
</Modal>
}
在Modal組件中,我使用this.props.show為自己添加一個不同的類。 如果為false,則會添加display:none來隱藏模態。
另一種方式是這樣的:
render(){
...
{ this.state.showModal &&
(<Modal>
// something in modal
</Modal>)
}
}
這使用showModal
來決定是否在渲染中添加模態。
我想弄清楚的是:
編輯:似乎不同的人有不同的偏好。 對我來說,我更喜歡@ErikTheDeveloper所說的。 顯示/隱藏模態的功能應該保留在模態中,當我們不需要顯示模態時,我們可以在模態中返回null。
我想也許沒有一個答案,哪種方式更好。 也許這只是個人選擇?
您的第一個示例始終呈現模式,但使用CSS隱藏/顯示它。
您的第二個示例僅在顯示時將模式插入到DOM中,否則它根本不會顯示在DOM中。
我不想渲染它,除非它是可見的(第二個例子),但我認為無論如何都不重要。 第二個例子現在也有更少的道具,因此Modal組件更簡單。
答案在於Modal組件的實現。 我希望它的render
方法是使用show
prop來正確優化標記。 您應該優化它以在未顯示時消除大部分標記。
為什么? 在Modal中實現優化簡化了其使用,其他組件不必意識到/擔心渲染它的成本。
編輯:因為我們使用React,與dom標記的成本相比,在v-dom中使用虛擬模態組件的成本可以忽略不計。 因此,即使你的其他組件最終在他們的v-dom中使用show = false來保持Modal,也無關緊要。
我也喜歡第二種方法。 盡管React最大限度地減少了在DOM中使用其他元素的負面影響,但是不渲染不具備的元素始終是一個好習慣。 我會擴展這個想法,並提取在單獨的函數中顯示/隱藏Modal的邏輯,並在渲染中調用它。
render: function(){
...
{this.renderModal()}
},
renderModal: function(){
...
{this.state.showModal && (<Modal />)}
}
這使您可以靈活地在單個位置添加其他條件,並使渲染功能保持小巧且易於理解。
我回答了一個類似的問題,有關開啟/關閉模態的最佳方式
從那以后,我花了很多時間在React上學習了一些課程。
我發現這種通用的方法可以很好地處理模態:使用一個完全控制的“啞”組件,需要3個道具。
有關受控組件的信息,請參閱React Docs
要回答關於兩者之間差異的問題,IMO選項1提供了更清晰,更靈活的API,而選項2更簡約。
使用選項1,您可以使用CSS 或從<Modal>
返回null
來處理隱藏/顯示。 我建議返回null
因為模態內容將不會被呈現而不是渲染它們並通過CSS“隱藏”它們。
選項2強制更有說服力的“JSX方式”有條件地渲染,我認為在許多情況下是合適的。 但是我覺得模態的概念值得隱藏/顯示是<Modal>
組件API的一部分(props / methods / etc ......)
為什么傳遞close
道具/回調?
考慮到大多數情態動詞都UX如關閉的事件,如:按[ESC],點擊“X”,點擊模式外,等...一個模式需要通過向下流過被告知如何“關閉自己” close
我的例子中的道具/回調。
// The simple, fully controlled Modal component
const Modal = React.createClass({
render() {
const {
show, // Boolean - Is the modal visible?
close, // Function - The modal needs a function to "close itself"
children, // node - The contents of the modal
} = this.props;
return !show ? null : (
<div className="some-class-for-styling">
<a onClick={close}>x</a>
{children}
</div>
);
}
});
const UsesModal = React.createClass({
setEditing(editing) {
this.setState({editing});
},
render() {
// `editing` could come from anywhere.
// Could be derived from props,
// or managed locally as state, anywhere really....
const {editing} = this.state;
return (
<div>
<h1>Some Great Component</h1>
<a onClick={() => this.setEditing(true)}>Show Modal!</a>
<Modal show={editing} close={() => this.setEditing(false)}>
Some great modal content... show based on UsesModal.state.editing
</Modal>
</div>
);
}
});
如果你想讓模態管理自己的狀態,你可以用一個稍微聰明的組件包裝“啞”模態並使用refs和“公共組件方法”(雖然我發現堅持使用簡化的方法通常會減少頭痛和后悔;))
const SmarterModal = React.createClass({
close() {
this.setState({show: false});
},
open() {
this.setState({show: true});
},
render() {
const {children} = this.props;
const {show} = this.state;
return (
<Modal show={show} close={this.close}>
{children}
</Modal>
);
}
});
const UsesSmarterModal = React.createClass({
render() {
return (
<div>
<h1>Some Great Component</h1>
<a onClick={() => this.refs.my_smarter_modal.open()}>Show Modal!</a>
<SmarterModal ref="my_smarter_modal">
Some great modal content... show based on SmarterModals own internal state
</SmarterModal>
</div>
);
}
});
有許多方法可以包含簡單的<Modal>
,但我覺得它可以作為一個堅實的基礎,數據流很好地允許計算/推導“從最有意義的地方開始模態”。 這是我發現很好地工作的方法。
這只是另一種方法, 如果模塊反應 :
var Node = require('react-if-comp');
...
var Test = React.createClass({
render: function() {
return <Node if={this.state.showModal}
then={<Modal>// something in modal</Modal>} />;
}
});
看看https://github.com/fckt/react-layer-stack ,它允許顯示/隱藏在樹的不同部分呈現的東西,但在邏輯上與頂級組件連接(允許使用來自它的變量):
import { Layer, LayerContext } from 'react-layer-stack'
// ... for each `object` in array of `objects`
const modalId = 'DeleteObjectConfirmation' + objects[rowIndex].id
return (
<Cell {...props}>
// the layer definition. The content will show up in the LayerStackMountPoint when `show(modalId)` be fired in LayerContext
<Layer use={[objects[rowIndex], rowIndex]} id={modalId}> {({
hideMe, // alias for `hide(modalId)`
index } // useful to know to set zIndex, for example
, e) => // access to the arguments (click event data in this example)
<Modal onClick={ hideMe } zIndex={(index + 1) * 1000}>
<ConfirmationDialog
title={ 'Delete' }
message={ "You're about to delete to " + '"' + objects[rowIndex].name + '"' }
confirmButton={ <Button type="primary">DELETE</Button> }
onConfirm={ this.handleDeleteObject.bind(this, objects[rowIndex].name, hideMe) } // hide after confirmation
close={ hideMe } />
</Modal> }
</Layer>
// this is the toggle for Layer with `id === modalId` can be defined everywhere in the components tree
<LayerContext id={ modalId }> {({showMe}) => // showMe is alias for `show(modalId)`
<div style={styles.iconOverlay} onClick={ (e) => showMe(e) }> // additional arguments can be passed (like event)
<Icon type="trash" />
</div> }
</LayerContext>
</Cell>)
// ...
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.