I am trying to get an animation (for now a fade) to play when clicking on the x of the chip. I have been able to hack together a fade in, so when I enter a new name, it fades in on arrival.
Now, I noticed the animation wouldn't play on exit (and I figured it was because its reference was being removed from the array, and that affected the call of map()). Really what I want to do is have the object animate away, and then be removed from the array.
When I try using a setTimeout to wait for the animation to complete, it starts applying the animation to neighboring elements in the array.
I do know why this is happening, but I simply do not know how to shift my code into the react paradigm and out of my stack/callback mindset and set up react to do what I'm asking it to.
import TextField from '@mui/material/TextField';
import { useRef, useState } from 'react';
import Container from '@mui/material/Container';
import Paper from '@mui/material/Paper';
import Chip from '@mui/material/Chip';
import { styled } from '@mui/material/styles';
import { useEffect } from 'react';
import { Transition } from 'react-transition-group';
const startList = [
{ name: "Ethan Anderson" },
{ name: "Olivia Brooks" },
{ name: "Mason Carter" },
{ name: "Ava Davis" }
];
function Student({ student, hDelete }) {
const nodeRef = useRef(null);
const [inProp, setIn] = useState(false);
useEffect(() => {
setIn(true);
}, [] );
const handleDelete = () => {
setIn(false);
setTimeout(() => hDelete(student), 320)
}
const duration = 300;
const defaultStyle = {
transition: `opacity ${duration}ms ease-in-out`,
opacity: 0,
}
const transitionStyles = {
entering: { opacity: 1 },
entered: { opacity: 1 },
exiting: { opacity: 0 },
exited: { opacity: 0 },
};
return (
<Transition
nodeRef={nodeRef}
in={inProp}
appear="true"
timeout={duration}
>
{state => (
<ListItem style={{ ...defaultStyle, ...transitionStyles[state] }}>
<Chip
variant="solid"
size="small"
sx={{
height: 'auto',
'& .MuiChip-label': {
display: 'block',
whiteSpace: 'normal',
},
}}
label={`${student.name}`}
onDelete={handleDelete}
/>
</ListItem>
)}
</Transition>
)
}
const ListItem = styled('li')(({ theme }) => ({
margin: theme.spacing(0.5),
}));
export default function CreateStudentForm() {
const nameRef = useRef(null);
const [people, setPeople] = useState([...startList]);
const handleKeyDown = (event, nextRef) => {
if (event.key === 'Enter') {
event.preventDefault();
console.log(nextRef.current.id);
if (nextRef.current.id !== "firstName") {
nextRef.current.focus();
} else {
let myObj = {
name: nameRef.current.value,
};
nameRef.current.value = '';
let newPeople = JSON.parse(JSON.stringify(people));
newPeople.push(myObj);
setPeople(newPeople);
console.log(newPeople);
nameRef.current.focus();
}
}
};
const handleDelete = (person) => {
let newPeople = JSON.parse(JSON.stringify(people));
let idx = people.findIndex((e) => e === person);
newPeople.splice(idx,1);
setPeople(newPeople);
};
return (
<Container maxWidth="md">
<TextField
fullWidth
id="firstName"
label="First Name"
size="small"
margin="normal"
inputRef={nameRef}
onKeyDown={(e) => handleKeyDown(e, nameRef)}
/>
<Paper
sx={{
display: 'flex',
justifyContent: 'center',
flexWrap: 'wrap',
listStyle: 'none',
p: 0.5,
m: 0,
}}
component="ul"
>
{people.map((data, i) => (
<Student key={i} student={data} hDelete={handleDelete} />
))}
</Paper>
</Container>
);
}
It seems like you're trying to implement a fade-out animation when a Chip is deleted from the list. The issue you're facing is that the animation is affecting neighboring elements when you use setTimeout to wait for the animation to complete before removing the item from the list.
To resolve this, you can utilize the Transition component from react-transition-group to manage the animation states for each Chip individually. Here's how you can modify your code to achieve this:
In this modification, I've removed the setTimeout from handleDelete function within the Student component. Instead, the hDelete function is called immediately after setting inProp to false. This ensures that the item is removed from the list only after the fade-out animation completes for that specific Chip.