React: Rendering a list in reverse order
Asked Answered
C

2

7

I'm building an app with React and Reflux, and I am trying to render a list of items in a specific order.

The items are custom Post components that are rendered in reverse chronological order, so the newest post is at the top of the list.

I am using Khan Academy's TimeoutTransitionGroup to have the list items fade in and out.

The problem I'm seeing is that when I add a new post and the component gets the updated list via new props, the transition happens on the last element in the list rather than the first. I would like to have it so that the first element fades in, since that's the position of the new item that was added.


Post 2 <- This post was newly added


Post 1 <- This post fades in


Is there a way to specify the same order of items, but render them in the reverse order, or something similar?

This is my component's render function:

    if (!(this.props.posts && this.props.ordering)) return false;
    var posts = this.props.ordering.map(function(postId, index) {
        return <Post key={index} post={this.props.posts[postId]}/>;
    }, this);
    return (
        <div className="post-collection">
            <TimeoutTransitionGroup 
                enterTimeout={500}
                leaveTimeout={500}  
                transitionName="postTransition">
                {posts}
            </TimeoutTransitionGroup>
        </div>
    );

This is the CSS transition:

.postTransition-enter {
    opacity: 0;
    transition: opacity .25s ease-in;
}

.postTransition-enter.postTransition-enter-active {
    opacity: 1;
}

.postTransition-leave {
    opacity: 1;
    transition: opacity .25s ease-in;
}

.postTransition-leave.postTransition-leave-active {
    opacity: 0;
}

Any help will be much appreciated!

Czerny answered 3/5, 2015 at 22:4 Comment(0)
S
18

You shouldn't use index as key, it defeats the purpose. For example, if you add an item to the beginning of the array, react will detect only one new key - the last one. All other components would be reconciled according to their keys. You should use unique id of a post as a key instead.

Staples answered 3/5, 2015 at 22:36 Comment(4)
Changing the key worked perfectly. It's so obvious now that you pointed it out. Thanks!Czerny
This is one of the trickiest parts of getting started with the ReactCSSTransitionGroup because React usually only complains about the key attribute when its just not there on elements/components that you're generating in a loop... since it doesn't complain for cases where the items are rerendered but their keys stay the same, this is much harder to figure out what is going on. Great answer!Valentine
damn! this indeed solved my problem. Thanks for the tip about not using the index as the component keyJewess
I always find using a string as an indicator plus a Math.random() the most useful for generating unique keys when there is no unique id to work with.Rocca
C
4

I had a similar issue but it seemed the op had an initial issue of how to properly utilize key in react. With that said this worked for reversing the ordering from ascending to descending.

var NotesList = React.createClass({
render: function () {
    var notes = this.props.notepad.notes;

    return (
        <div className="note-list">
            {
                notes.reverse().map(function (note) {
                    return (
                        <NoteSummary key={note.id} note={note}/>
                    );
                })
            }
        </div>
    );
}
});
Caitiff answered 9/8, 2016 at 20:55 Comment(8)
this will modify the original array you should use [...notes].reverse()Paschal
@fareednamrouti can you explain what is wrong with modifying the original array? What is the complete syntax and I will adjust it. Thanks.Caitiff
modifying the original data will lead to many problems: 1- this will prevent the component from knowing if this property has changed or not so it might not re-render itself again 2- every time your component render it will reverse the array again, I suggest you read more about Functional Programming and ReduxPaschal
I don't remember if this is my exact implementation but it works as expected. Again, I am not seeing what you posted i.e. [notes].reverse()... and what I posted... I guess that is the confusionCaitiff
[...notes] will just copy the array you can also use notes.concat(), the reverse function of the array will modify the original array and it's not right thing todoPaschal
@ChristianMatthew if you modify the original array and save it then request it back your array will save in reverse. And you will keep reversing it if you make changes. Making your array flip flop.Myelencephalon
@Myelencephalon you're saying save... there is not a save going on here. this is referring to what is on screen to the end userCaitiff
@ChristianMatthew I am speaking theoretically. Another example, If you have this component nested and it lets say gets updated, then it reverses, and if it gets updated again then it reverses again, flipping.Myelencephalon

© 2022 - 2024 — McMap. All rights reserved.