J'ai construit un simple système add-your-todos dans React en utilisant Semantic-UI-React. Il ressemble actuellement à ceci:

before-transition-attempt

Description du problème et ma tentative

Lorsque l'utilisateur clique sur l'icône de la corbeille rouge, je souhaite supprimer la Table.Row à l'aide d'une transition en fondu . Il supprime actuellement la ligne, mais une animation ici rendrait l'expérience utilisateur plus agréable. J'ai consulté la documentation et essayé de mettre en œuvre la solution, à l'aide d'un composant Transition.Group.

... mais cela n'a pas bien fonctionné

Après avoir essayé de résoudre ce problème par moi-même, j'ai eu des comportements inattendus. Tout d'abord, les lignes ne s'estompent pas. En outre, tous les types de Table.Cell de "mélange" dans une seule cellule, ce qui est ennuyeux. Voir le résultat (horrible):

after-transition-attempt

Le composant Todo (avant)

Chaque ligne Todo est ajoutée dynamiquement à la table à l'aide d'un composant Todo, qui, avant d'implémenter Transition.Group, ressemblait à ceci:

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;

Le composant (après)

Voici à quoi ça ressemble maintenant (ce qui est évidemment faux!):

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;

Toute aide offerte sera grandement appréciée!


MODIFIER

La réponse de @ Adrien a partiellement résolu mon problème. Maintenant, chaque cellule est à sa place, mais la transition d'animation ne semble pas jouer. De plus, l'icône de calendrier à côté de mes cases à cocher «complétées» (vérifiez la version initiale non modifiée de l'application) semble disparaître. Une idée de la raison pour laquelle ces deux choses se produisent? Voir:

still-not-quite-right

2
Jose Lopez Garcia 12 août 2017 à 17:35

2 réponses

Les réponses précédentes vous ont déjà indiqué la bonne manière. J'ai fait un exemple de minimal qui montre comment cela fonctionne.

Comme MEnf l'a dit, Transition.Group ne fonctionne que sur mount / unmount, dans le contexte de React cela signifie que l'animation démarrera lorsque le composant sera ajouté en tant que nouvel enfant ou sera supprimé.

2
Oleksandr Fediashov 15 août 2017 à 11:08

La raison pour laquelle votre animation ne fonctionne pas est que, selon la documentation, Transition.Group ne fonctionnera que lors du montage / démontage d'un composant. Supprimez l'attribut visible de la balise Transition.Group. Remplacez as={Table.Row} par as={Table.Body}. Par démontage / montage, je veux dire chaque fois qu'un nouvel élément est ajouté à votre tableau Todo, il doit soit restituer un nouveau composant de ligne todo sur la page, soit le supprimer au lieu de le cacher / l'afficher.

* édité pour clarification

1
MEnf 14 août 2017 à 21:53