![](/img/trans.png)
[英]How does React re-use child components / keep the state of child components when re-rendering the parent component?
[英]Mutating child components based on parent component's state, without re-rendering
目標
我正在嘗試從父組件管理mouseenter和mouseleave事件,以獲取不斷重新呈現的子組件的集合。
我正在為清單的集合構建一個可重用的組件,它可以完成諸如分頁之類的幾項工作,以及在懸停清單時執行的其他一些工作。
因此,要使其可重用,我必須維護父CollectionComponent
懸停列表的狀態,並根據父狀態對每個單獨的列表組件進行突變。
碼
這是我正在使用的組件(我將它們剝離為最基本的形式):
列表組件:
import React from 'react'
import $ from 'jquery'
import CollectionComponent from './CollectionComponent'
import Listing from './Listing'
export default class Listings extends React.Component {
constructor(props) {
super(props)
this.state = {
listings: this.props.listings,
}
}
render() {
return (<section className="listing-results">
{this.state.listings.map( listing =>
<CollectionComponent results={this.state.listings} IndividualResult={Listing} perPage={this.props.perPage} options={options}/>
)}
</section>)
}
}
收集組件:
import React from 'react'
export default class CollectionComponent extends React.Component {
constructor(props) {
super(props)
this.state = {
results: this.props.results,
hoveredId: null
}
}
componentDidMount() {
this.$listings = $('.result-card')
$(this.$listings).mouseenter(this.toggleInfoIn).mouseleave(this.toggleInfoOut)
}
toggleInfoIn = e => {
var { target } = e
var infoId = $(target).data('id')
this.setState({hoveredId: infoId})
}
toggleInfoOut = e => {
this.setState({hoveredId: null})
}
render() {
const {results, IndividualResult, perPage, options} = this.props
return (
<div className="paginated-results">
{this.state.results.map( result =>
<IndividualResult key={result.id} result={result} options={options}/>
)}
</div>
)
}
}
個別列表組件:
import React from 'react'
export default class Listing extends React.Component {
constructor(props) {
super(props)
}
render() {
const { listing, hoveredId } = this.props
return (
<div className="result-card" data-id={listing.id}>
<div className={hoveredId === listing.id ? 'hovered' : ''}>
Listing Content
</div>
</div>
)
}
}
我知道我可以用更高階的組件來構造一個更干凈的CollectionComponent
,但是一旦我在基本設置中正常使用它,我將把它留待以后重構。
問題
我的問題是,每次我懸停並更改父組件的狀態時,它都會重新渲染子組件,因為它們的道具取決於父組件的狀態。 一旦發生這種情況,對我的jQuery清單集合的引用將不再有效。 因此,鼠標事件將附加到不再存在的舊DOM元素上。
我如何以不同的方式構造它,以便:
我真的很想避免每次組件更新時都得到一個新的jQuery集合。
懸停行為應僅限於單獨的列表組件,而不是集合組件。
當Collections
組件保持當前懸停的項目的狀態時,最好將處理程序作為prop的一部分傳遞,然后根據Collections
組件設置的狀態更改再次呈現列表。
如有必要,請使用基於React的事件處理程序,以使其成為受控組件。 在DOM
中放置狀態不是一個好主意,反應可以為您處理狀態。
清單
import React from 'react'
export default class Listing extends React.Component {
constructor(props) {
super(props);
this.onMouseEnter = this.onMouseEnter.bind(this);
this.onMouseLeave = this.onMouseLeave.bind(this);
}
onMouseEnter() {
this.props.onMouseEnter({ listingId: this.props.listing.id });
}
onMouseLeave() {
this.props.onMouseLeave();
}
render() {
const { listing, hoveredId } = this.props
const listingId = listing.id;
const isHovered = this.props.hoveredId === listing.id;
return (
<div className="result-card" onMouseEnter={this.onMouseEnter} onMouseLeave={onMouseLeave}>
<div className={isHovered ? 'hovered' : ''}>
Listing Content
</div>
</div>
)
}
}
館藏
import React from 'react'
export default class CollectionComponent extends React.Component {
constructor(props) {
super(props)
this.state = {
results: this.props.results,
hoveredId: null
}
}
onMouseEnter({ listingId }) {
this.setState({ listingId });
}
onMouseLeave() {
this.setState({ listingId: null });
}
render() {
const {results, IndividualResult, perPage, options} = this.props
return (
<div className="paginated-results">
{this.state.results.map( result =>
<IndividualResult key={result.id} hoveredId={this.state.hoveredId} result={result} options={options} onMouseEnter={this.onMouseEnter} onMouseLeave={this.onMouseLeave}/>
)}
</div>
)
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.