chevron-left chevron-right

Piotr Nalepa Frontend, architecture and AI

[JS] Jak zaktualizować wygląd elementu po zmianie stanu atrybutu w React.js?

This version
blog.piotrnalepa.pl/2015/07/02/js-jak-zaktualizowac-wyglad-elementu-po-zmianie-stanu-atrybutu-w-react-js
Published
Author
, Staff Software Engineer
Category
JavaScript
Feedback
Write to me · Post on X

This post is 11 years old. Browsers and tools may have changed since then, so check the code against current documentation before you use it.

Ostatnio postanowiłem sprawdzić czym jest React.js? Od dłuższego czasu miałem świadomość istnienia tej biblioteki do obsługi widoków w aplikacjach JS. W trakcie testowania możliwości React.js napotkałem się z problemem aktualizacji widoku po zmianie stanu/wartości jednego z atrybutów widoku.

Problem polegał na tym, że w trakcie działania aplikacji postanowiłem aktualizować wartości wyświetlane w danym elemencie strony (na potrzeby tego tekstu załóżmy że był to licznik aktywnych użytkowników) a po aktualizacji wartości chciałem aby została uruchomiona animacja.

Szukałem rozwiązania tego problemu i okazało się (być może nie szukałem zbyt dokładnie), że React.js nie obsługuje możliwości zmiany stanu już istniejącego elementu. To znaczy, może zmieniać stan podczas dodawania elementu lub jego usuwania, ale w momencie gdy następuje aktualizacja danych, to implementacja zamierzonej animacji (chwilowe powiększenie elementu i powrót do poprzedniego wyglądu) jest niemożliwa.

Section 1Rozwiązanie problemu - aktualizacja wyglądu elementu po zmianie wartości atrybutu

Proponowane przeze mnie rozwiązanie opiera się na fakcie, że React.js monitoruje zmiany wartości klucza identyfikującego dany element - atrybut key. Gdy następuje zmiana wartości tego atrybutu, to React.js ponownie renderuje dany element.

Kod, który jest odpowiedzialny za takie działanie wygląda następująco:

Example 1JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
'use strict';
 
var React = require('../../../node_modules/react/addons'),
    ReactCSSTransitionGroup = React.addons.CSSTransitionGroup,
    NotificationItem;
 
(function () {
    NotificationItem = React.createClass({
        // Obsługa sytuacji, gdy następuje aktualizacja danych widoku
        // W tym przypadku, aktualizuje stan licznika liczby osób
        componentWillReceiveProps: function (nextProps) {
            this.setState({usersCount: nextProps.item.users.length});
        },
 
        getInitialState: function () {
            return {
                onClick: function () { console.log('notification:click'); },
                notificationType: 'default',
                updates: [],
                updatesCount: 0
            };
        },
 
        render: function () {
            var key = this.state.notificationType + '-notification-' + this.state.usersCount;
 
            return (
                <a className="notification" href="#" key={key} onClick={this.state.onClick}>
                    <ReactCSSTransitionGroup transitionName="update">
                        <span className="badge new">{this.state.usersCount}</span>
                    </ReactCSSTransitionGroup>
                </a>
            );
        }
    });
})();

Do powyższego kodu JavaScript możemy dołożyć kod CSS w którym będą zdefniowane reguły odpowiedzialne za animację, np.:

Example 2CSS
1
2
3
4
5
6
7
8
9
10
.notification {
    background: green;
    animation: notify .5s 2;
}
 
@keyframes notify {
    0% { transform: scale(0); }
    50% { transform: scale(1.5); }
    100% { transform: scale(1); }
}

W momencie gdy element zostanie od nowa wyrenderowany to animacja powinna się uruchomić.

Zapraszam do komentowania i dzielenia się swoimi uwagami.

Share
Feedback

About the author

Staff Software Engineer

I've been writing this blog since 2009 and building for the web professionally for 14 years. Today I lead the frontend of the Cosmos platform at Bishop Fox, where I've been since day one of the project. Before that I worked at OLX, KUDO, Auto1 and eZ Systems. Here I write about what I've learned in practice: JavaScript, TypeScript, React, CSS and frontend architecture. I've also spoken at conferences across Poland and Europe. Got a question or an idea for a post? Let me know!