[英]React : How to apply the state change to all instances of a Component, even if the state of any one instance of component is changed?
[英]In ReactJS is component state tied to an instance of the component or is it tied to all instances of the component?
我正在嘗試在頁面上顯示組件的多個實例。 每個實例都應出現在Tab.Pane(語義UI功能)中。 但是,在嘗試實現這一點時,我遇到了一些奇怪的行為,如下文更詳細地解釋。
我有一個組成部分; <MultistepFilterSection />
在此組件中,狀態為:
this.state = {
conjunction: "AND" // default
}
該狀態由組件中的onClick處理函數修改;
handleConjunctionButtonClick = (conjunction, e) => {
this.setState({conjunction: conjunction})
}
通過單擊兩個按鈕之一來觸發此onClick:
<Button.Group vertical>
<Button
onClick={(e) => this.handleConjunctionButtonClick("AND")}
color={this.state.conjunction === "AND" ? "blue" : null}
>
And
</Button>
<Button
onClick={(e) => this.handleConjunctionButtonClick("OR")}
color={this.state.conjunction === "OR" ? "blue" : null}
>
Or
</Button>
</Button.Group>
我正在使用語義UI的Tab組件在頁面上呈現此組件的3個實例;
const panes = [
{
menuItem: "Panel Data",
render: () =>
<Tab.Pane attached={false}>
<MultistepFilterSection getAudience={this.getAudience} />
</Tab.Pane>
},
{
menuItem: "Geolocation Data",
render: () =>
<Tab.Pane attached={false}>
<MultistepFilterSection getAudience={this.getAudience} />
</Tab.Pane>
},
{
menuItem: "Combined Audience Selection",
render: () =>
<Tab.Pane attached={false}>
<MultistepFilterSection getAudience={this.getAudience} />
</Tab.Pane>
}
]
在render方法中,我有:
<Tab
menu={{ secondary: true, pointing: true }}
panes={panes}
/>
在任何一個選項卡中觸發onClick處理程序都會更改組件所有實例中的狀態。 這正常嗎? 我認為組件的一個實例中的組件狀態是該實例所獨有的。
在進一步的調查中,我發現使用語義UI的Tab組件實例化<MultistepFilterSection />
多個實例時,會表現出這種行為。 當單獨渲染實例時,展覽的預期行為。
<MultistepFilterSection />
組件的完整代碼:
import React from "react";
import { Grid, Button, Container, Icon, Segment } from "semantic-ui-react";
import { connect } from "react-redux";
import uuid from "uuid";
import _ from "lodash";
import RuleGroup from "../rules/RuleGroup";
import { filterGroupCreated, filterGroupDeleted, filterDeleted } from "../../actions/FiltersAction"
export class MultistepFilterSection extends React.Component {
constructor(props) {
super(props);
this.state = {
conjunction: "AND" // default
}
// create one default group
this.props.filterGroupCreated({filterGroupId: uuid()})
this.handleAddRuleGroupButtonClick = this.handleAddRuleGroupButtonClick.bind(this);
this.renderRuleGroups = this.renderRuleGroups.bind(this);
this.handleConjunctionButtonClick.bind(this)
}
handleAddRuleGroupButtonClick() {
// console.log("called handleAddRuleGroupButtonClick()")
const filterGroupId = uuid()
let data = {}
data.filterGroupId = filterGroupId
this.props.filterGroupCreated(data)
}
handleConjunctionButtonClick = (conjunction, e) => {
this.setState({conjunction: conjunction})
}
renderRuleGroups() {
// console.log("called renderRuleGroups()")
return Object.values(this.props.filterGroups).map(function(ruleGroup) {
const key = ruleGroup.id;
// incomplete
let currentGenderSelected
return (
<React.Fragment key={key}>
<RuleGroup
id={key}
key={key}
deleteRuleGroup={this.deleteRuleGroup}
deleteFilter={this.deleteFilter}
currentGenderSelected={currentGenderSelected}
/>
</React.Fragment>
)
}.bind(this))
}
deleteRuleGroup = (id, e) => {
// console.log("delete rule group called")
this.props.filterGroupDeleted({filterGroupId: id})
}
deleteFilter = (filterGroupId, filterId, e) => {
// console.log("deleteFilter() called")
this.props.filterDeleted({
filterGroupId: filterGroupId,
filterId: filterId
})
}
render() {
const isFilterGroupQuery = true
return(
<Grid padded="vertically">
<Grid.Row stretched>
<Grid.Column verticalAlign={"middle"} width={2}>
{_.size(this.props.filterGroups) > 0 &&
<Segment basic>
<Button.Group vertical>
<Button
onClick={(e) => this.handleConjunctionButtonClick("AND")}
color={this.state.conjunction === "AND" ? "blue" : null}
>
And
</Button>
<Button
onClick={(e) => this.handleConjunctionButtonClick("OR")}
color={this.state.conjunction === "OR" ? "blue" : null}
>
Or
</Button>
</Button.Group>
</Segment>
}
</Grid.Column>
<Grid.Column width={14}>
{this.renderRuleGroups()}
</Grid.Column>
</Grid.Row>
<Grid.Row>
<Grid.Column width={2}></Grid.Column>
<Grid.Column width={3}>
<Button
color="grey"
basic
onClick={this.handleAddRuleGroupButtonClick}
>
<Icon name="plus" />Add Rule Group
</Button>
</Grid.Column>
<Grid.Column width={11}>
<Button
color="blue"
onClick={
(isFilterGroupQuery) => this.props.getAudience(
isFilterGroupQuery, this.state.conjunction
)
}
floated={"right"}
>
Run query
</Button>
</Grid.Column>
</Grid.Row>
</Grid>
)
}
}
function mapStateToProps(state) {
return {
filterGroups: state.filters
};
}
export default connect(
mapStateToProps,
{
filterGroupCreated,
filterGroupDeleted,
filterDeleted
}
)(MultistepFilterSection);
經過深入研究並最終在Semantic UI的GitHub存儲庫上發布了一個問題 ,我了解到我需要在Tab組件上使用renderActiveOnly={false}
。 我還必須更改標記,以便窗格對象采用以下格式:
const panes = [
{
key: 1,
menuItem: "Panel Data",
pane: <Tab.Pane><Simple key={1} /></Tab.Pane>
},
{
key: 2,
menuItem: "Geolocation Data",
pane: <Tab.Pane><Simple key={2} /></Tab.Pane>
}
]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.