I have an array of users/persons that I am trying to map. In this case they will just appear on in row, where they can be clicked, and then it will add a class, which just scales the mapped item. However, the issue is that I can click multiple items, and then they will individually scale up or down depending on the state of the toggle. What I would like to do is when I click one, every other will scale down, so that there is only one scaled at a time.
But I am not quite sure how to proceed. My main component and the component that is being mapped is seen below. I can see that by putting the click event in the PersonHeader component they are kind of independent of each other. But again, I'm not sure how to "connect" them, so they know each other states.
Main component:
import { memo, useState } from 'react'
import cx from 'clsx'
import styles from './person.module.scss'
import PersonContent from './person-content/person-content.component'
interface IPerson {
person: any
}
const Person = ({ person }: IPerson) => {
return (
<>
<div
className={styles['person-wrapper']}
>
<div>
{Array.isArray(person.users) &&
person.users.map(user => (
<PersonHeader
name={user.name}
></PersonHeader>
))}
</div>
</div>
</>
)
}
export default memo(Person)
Person component:
import { memo, useState } from 'react'
import cx from 'clsx'
import styles from './person-header.module.scss'
interface IPersonHeader {
name: string
}
const PersonHeader = ({ name }: IPersonHeader) => {
const [personToggle, setPersonToggle] = useState(false)
return (
<>
<div
onClick={() => setPersonToggle(!personToggle)}
className={cx(styles['person'], {
[styles['is-active']]: personToggle,
})}
>
<div>{name}</div>
</div>
</>
)
}
export default memo(PersonHeader)
CSS:
.person {
display: grid;
position: relative;
cursor: pointer;
transition: transform 0.1s ease-in-out;
&.is-active {
transform: scale(1.2);
transition: transform 0.1s ease-in-out;
}
}