I've built a simple add-your-todos system in React using Semantic-UI-React. It currently looks like this:
Problem description, and my attempt
When the user clicks on the red bin icon, I'd like to delete the Table.Row using a Fadeout Transition. It currently deletes the row, but an animation here would make the user experience more enjoyable. I've visited the docs and tried to implement the solution, using a Transition.Group component.
...but it didn't work well
After trying to solve this problem on my own, I got some unexpected behaviours. First of all, rows don't fadeout. Furthermore, all Table.Cell kind of "blend" into one single cell, which is annoying. See the (gruesome) result:
The Todo component (before)
Each Todo row is being dynamically added on the Table using a Todo component, which, before implementing Transition.Group, looked like this:
const React = require('react');
const moment = require('moment');
import { Table, Checkbox, Icon, Popup, Grid, Button } from 'semantic-ui-react';
class Todo extends React.Component {
constructor(props) {
super(props);
}
render() {
const { id, text, completed, createdAt, completedAt } = this.props;
const renderDate = (date) => {
const timestamp = date;
if (timestamp)
return `${moment.unix(timestamp).format('MMM Do YYYY @ h:mm a')}`;
return '';
}
const renderPopup = () => {
if (completedAt) {
return (
<Popup trigger={<Icon name="calendar check" size="large"/>} header={'Completed at'} content={renderDate(completedAt)}/>
);
} else {
return (
''
);
}
}
return (
<Table.Row>
<Table.Cell>
<Grid columns="equal">
<Grid.Column width={3}>
<Checkbox toggle
defaultChecked={completed}
onClick={() => this.props.onToggle(id)} />
</Grid.Column>
<Grid.Column textAlign="left">
{renderPopup()}
</Grid.Column>
</Grid>
</Table.Cell>
<Table.Cell>{text}</Table.Cell>
<Table.Cell>{renderDate(createdAt)}</Table.Cell>
<Table.Cell textAlign="right">
<Button basic color="red" icon="trash"
onClick={() => {
this.props.onRemoveTodo(id);
this.handleFadeoutItem();
}}/>
</Table.Cell>
</Table.Row>
);
}
}
module.exports = Todo;
The component (after)
This is how it looks now (which is obviously wrong!):
const React = require('react');
const moment = require('moment');
import { Table, Checkbox, Icon, Popup, Grid, Button, Transition } from 'semantic-ui-react';
class Todo extends React.Component {
constructor(props) {
super(props);
this.state = {
visible: true
};
this.handleFadeoutItem = this.handleFadeoutItem.bind(this);
}
handleFadeoutItem () {
this.setState({
visible: false
});
}
render() {
const { visible } = this.state;
const { id, text, completed, createdAt, completedAt } = this.props;
const renderDate = (date) => {
const timestamp = date;
if (timestamp)
return `${moment.unix(timestamp).format('MMM Do YYYY @ h:mm a')}`;
return '';
}
const renderPopup = () => {
if (completedAt) {
return (
<Popup trigger={<Icon name="calendar check" size="large"/>} header={'Completed at'} content={renderDate(completedAt)}/>
);
} else {
return (
''
);
}
}
return (
<Transition.Group as={Table.Row} visible={visible} animation="fade" duration={500}>
<Table.Row>
<Table.Cell>
<Grid columns="equal">
<Grid.Column width={3}>
<Checkbox toggle
defaultChecked={completed}
onClick={() => this.props.onToggle(id)} />
</Grid.Column>
<Grid.Column textAlign="left">
{renderPopup()}
</Grid.Column>
</Grid>
</Table.Cell>
<Table.Cell>{text}</Table.Cell>
<Table.Cell>{renderDate(createdAt)}</Table.Cell>
<Table.Cell textAlign="right">
<Button basic color="red" icon="trash"
onClick={() => {
this.props.onRemoveTodo(id);
this.handleFadeoutItem();
}}/>
</Table.Cell>
</Table.Row>
</Transition.Group>
);
}
}
module.exports = Todo;
Any help offered will be greatly appreciated!
EDIT
@Adrien's answer partially solved my problem. Now every cell is in its place, but the animation transition doesn't seem to play. Furthermore, the calendar icon next to my "completed" checkboxes (check the initial, unmodified version of the app) seem to disappear. Any idea why these two things happen? See:


