I have a React Component and I am creating 2 copies of it. However, when the state of 1 of them is updated, it updates the 2nd one too. I am not sure what is causing this.
Here is my code:
This is the place where I am using 2 components:
{this.state.selectedTab === 0 ?
<Carousel
size={1}
cultureInfo={this.state.cultureInfo}
collaboratorError={this.state.activeCollaborationError}
getPinnedError={this.state.getPinnedUsersError}
pinActionError={this.state.isPinnedServerError}
user={this.state.activeCollaboratorContactsData}
isPinnedTab={false}
startDate={this.state.startDate}
isMapped={this.state.isMapped}
resetPosition={this.state.resetCollabCarousel}
isVisible={this.state.selectedTab === 0 }
/>
:
<Carousel
size={1}
cultureInfo={this.state.cultureInfo}
collaboratorError={this.state.activeCollaborationError}
getPinnedError={this.state.getPinnedUsersError}
pinActionError={this.state.isPinnedServerError}
user={this.state.pinnedUsers}
isPinnedTab={true}
startDate={this.state.startDate}
isMapped={this.state.isMapped}
resetPosition={this.state.resetPinnedCarousel}
isVisible={this.state.selectedTab === 1}
/>
}
Here is the Carousel Code:
interface ICarouselProps {
size: number;
cultureInfo: CultureInfo;
collaboratorError: Error.DataLayerError;
getPinnedError: Error.DataLayerError;
pinActionError: Error.DataLayerError;
user: ActiveCollaboratorContact[];
isPinnedTab: boolean;
startDate: Date;
isMapped: boolean;
resetPosition: boolean;
isVisible: boolean;
}
interface ICarouselState {
position: number;
width: number;
isActiveNext: boolean;
isActivePrev: boolean;
isActive: number;
}
const numSlides = 2;
const width = 100;
const move = width / numSlides;
const max = width - move;
const min = -max;
const numOfCards = 4;
export default class Carousel extends BaseComponent<ICarouselProps,
ICarouselState> {
constructor() {
super();
this.resetState();
}
componentWillReceiveProps(newProps: ICarouselProps): void {
if (newProps && newProps.resetPosition) {
this.resetState();
}
}
doRender(): React.ReactElement<{}> {
let wrapperWidth: number;
let widthStyle: string;
wrapperWidth = (this.state as ICarouselState).width;
const style: React.CSSProperties = {
WebkitTransform: "translateX(" + this.state.position + "%)",
transform: "translateX(" + this.state.position + "%)",
MozTransform: "translateX(" + this.state.position + "%)",
msTransform: "translateX(" + this.state.position + "%)",
OTransform: "translateX(" + this.state.position + "%)",
width: wrapperWidth + "%"
} as React.CSSProperties;
const slideWidth: React.CSSProperties = {width: move + "%"} as React.CSSProperties;
let nextIsDisabled: boolean;
let prevIsDisabled: boolean;
let slideActive: string;
widthStyle = (this.props.size === 0) ? styles.vCard : styles.hCard;
nextIsDisabled = !this.state.isActiveNext;
prevIsDisabled = !this.state.isActivePrev;
slideActive = "slideActive" + this.state.isActive;
const totalUsers = this.props.user.length;
const articles: JSX.Element[] = [];
for (let i = 0; i < 2; i++) {
const cards: JSX.Element[] = [];
for (let j = 0; j < numOfCards; j++) {
const userIndex = i * numOfCards + j;
if (userIndex < totalUsers) {
const card: JSX.Element = <Card
cultureInfo={this.props.cultureInfo}
user={this.props.user[userIndex]}
startDate={this.props.startDate}
extraMargin={userIndex % numOfCards === 0}
/>;
cards.push(card);
}
}
const article: JSX.Element =
<article className={styles.slideSingle}
tabIndex={0}
style={slideWidth}>
{cards}
</article>;
articles.push(article);
}
return this.props.isVisible ?
<div>
<div className={widthStyle + " " + styles.carousel + " " + slideActive} tabIndex={-1} id="Carousel">
<div className={styles.slideWrapper}
style={style}>
{articles}
</div>
<nav className={styles.nav}>
<ul className={styles.arrows}>
<li className={styles.stepLeft}>
<a disabled={prevIsDisabled} aria-disabled={prevIsDisabled} className={styles.previous} href="#"
tabIndex={0}
onClick = {this.prevSlideClicked}>
BUTTONPREVTEXT
</a>
</li>
<li className={styles.stepRight}>
<a disabled={nextIsDisabled} aria-disabled={nextIsDisabled} className={styles.next} href="#"
tabIndex={0}
onClick = {this.nextSlideClicked}>BUTTONNEXTTEXT
</a>
</li>
</ul>
</nav>
</div>
</div> :
null;
};
private resetState(): void {
const newState: ICarouselState = {
position: 0,
width: numSlides * 100,
isActiveNext: true,
isActivePrev: false,
isActive: 0
};
if (this.state) {
this.setState(newState);
} else {
this.state = newState;
}
}
private nextSlideClicked: () => void = () => {
if (this.state.position > min + move) {
this.setState({
position: this.state.position - move,
width: numSlides * 100,
isActiveNext: true,
isActivePrev: true,
isActive: Math.abs((this.state.position - move) / move)
});
} else if ((this.state as ICarouselState).position > min) {
this.setState({
position: this.state.position - move,
width: numSlides * 100,
isActiveNext: false,
isActivePrev: true,
isActive: Math.abs((this.state.position - move) / move)
});
}
};
private prevSlideClicked: () => void = () => {
if (this.state.position < 0 - move) {
this.setState({
position: this.state.position + move,
width: numSlides * 100,
isActiveNext: true,
isActivePrev: true,
isActive: Math.abs((this.state.position + move) / move)
});
} else if (this.state.position < 0) {
this.setState({
position: this.state.position + move,
width: numSlides * 100,
isActiveNext: true,
isActivePrev: false,
isActive: Math.abs((this.state.position + move) / move)
});
}
};
private getCarouselName(): CarouselNames {
return "name"
}
};
Thanks.
I had the same problem. I set a distinct 'key' property on each instance and the problem went away.
If you are using the same component for a different route (react-router
) then you have to set key
property for each route.
Keys help React identify which items have changed, are added, or are removed.
For this kind of situation where you want to use the same component multiple times, you have to set key
property. Otherwise, each component will have the same state.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With