Solution 1 :

I can’t see the code where you iterate over the notifications to create Notification components.

I assume you have a notifications.map(...) somewhere… To only re-render new components, use the key={...} attribute inside of the map, with a value unique to each attribute (use index if you don’t have a unique key).

e.g.

<div>
    { notifications.map((notification) => <Notification
        key={notification.id}
        notification={notification}
        />)
    }
</div>

Solution 2 :

Figured out what was wrong:

I had a <ul></ul> tag surrounding my <li></li> tag in my Notification class.

Removed this and all is working as it should.

Problem :

I have a web app that uses a websocket to receive information from an API I have put together.

Everything works great, however, every time new information arrives from the websocket, the whole list on my frontend (React) is updated.

Here is the relevent code:

    componentDidMount(prevState) {
        socketIO.on('newNotification', (response) => {
            const notifications = this.state.notifications;
            console.log(response)
            const newNotifications = response.data

            this.setState(prevState => ({
                notifications: [...this.state.notifications, newNotifications]
            }))

        });
    }

notifications is a list of notifications that is received from my API, which I set to the state.notifications whenever a response is received.

My understanding is React only updates what it needs to, so I’m not sure what is going on.

Here is my Notification component:

import React from "react"

class Notification extends React.Component {


    render(){
        return(
            <ul>
              <li 
                key = {this.props.notification.id}
                onClick={() => this.props.deleteNotificationProps(this.props.notification.id)}>
                <div className='separator-container'>
                    <div className={'notification-border ' + this.props.notification.stat_abr}>
                        <div className='notification' >
                        <div className='left-notification'>
                            <div className = 'stat-abr'>{this.props.notification.stat_abr}</div>
                            <div className = 'game-time'>{this.props.notification.game_time_string}</div>  
                        </div>
                        <div className='middle-notification'>
                        <div className='player-image'>
                            <img src={"http://nhl.bamcontent.com/images/headshots/current/168x168/" + this.props.notification.player_id.toString() + ".jpg"} alt="" className="player-img" />
                            </div>
                        </div>
                        <div className = 'right-notification'> {this.props.notification.description} </div>
                        </div>
                    </div>
                    </div>
              </li>
            </ul>
        )
    }
}

export default Notification

I tried various diferent methods of updating the state, but nothing seems to work.

EDIT: here is the NotificationList class where the Notification component is created:

class NotificationList extends React.Component {
    render() {
        return(
            <ul>
            {this.props.notifications.map(notification => (
              <Notification 
                id = {notification.id}
                notification = {notification}
                handleChangeProps = {this.props.handleChangeProps}
                deleteNotificationProps = {this.props.deleteNotificationProps}
              />
            ))}
          </ul>
        )
    }
}

Comments

Comment posted by dvdrplus

Thanks @Nick Grealy. I have included the map function in my original post. I have changed this to be “key” instead of “id”, however my whole array is being rerendered still. Maybe I am misinterpretting, but I have a CSS class that is only applied for the first 10 seconds after a notification is created. When a new notification arrives, the whole list is reloaded and the CSS is applied to the whole list

Comment posted by Nick Grealy

Absolutely my pleasure!

Comment posted by dvdrplus

Just recommenting, I didn’t mean to click enter so soon on my previous comment

Comment posted by Nick Grealy

Check your JSX hierarchy. If a parent component is re-rendered, so too, will all it’s children. You can also try wrapping your JSX element in a

By