I'm learning React and Redux and followed the tutorial on the Redux site. I'm trying to add a feature that lets user sort the todos by name, date, etc. The problem is the todo list doesn't rerender itself when I sort the array of todos. The state.sortBy is dispatched by different component and it's working. I can clearly see that the array is sorted by logging store.getState() to console. And the component is of course subscribed to the store.
The array changes. When I sort by "date" it's sorted by date. When I sort by "name" it's sorted by name. But the todo list component ignores it and doesn't rerender.
Here's the code for the todo list container component:
import { connect } from 'react-redux'
import TodoList from '../components/TodoList'
import { toggleTodo } from '../actions'
const sortTodos = (todos, sortBy) => {
  switch (sortBy) {
    case "date":
      return todos.sort((a, b) => Date.parse(b.date) - Date.parse(a.date))
    case "name":
      return todos.sort((a, b) => {
        if (a.name < b.name)
          return -1
        if (a.name > b.name)
          return 1
        return 0
      })
    default:
      return todos
  }
}
const mapStateToProps = (state) => ({
  todos: sortTodos(state.todos, state.sortBy)
})
const mapDispatchToProps = (dispatch) => ({
  onTodoClick: (id) => dispatch(toggleTodo(id))
})
export default connect(
  mapStateToProps,
  mapDispatchToProps
)(TodoList)
And here is the presentational component:
import React from 'react'
import Todo from './Todo'
const TodoList = ({ todos, onTodoClick }) =>
  <ul>
    {todos.map((todo) =>
      <Todo
        key={todo.id}
        {...todo}
        onClick={() => onTodoClick(todo.id)}
      />
    )}
  </ul>
export default TodoList
I've tried couple things and I got it working, but I think it's not the correct way to do this. When I appended .slice(0, -1) to the return statement of sortTodos function, the component rerendered.
const sortTodos = (todos, sortBy) => {
  switch (sortBy) {
    case "date":
      return todos.sort((a, b) => Date.parse(b.date) - Date.parse(a.date)).slice(0, -1)
.
.
.
Thanks for help
sort does inplace array sorting (modifies the array itself). You need to make a copy before sorting. For example
todos.slice(0).sort((a, b) => Date.parse(b.date) - Date.parse(a.date))
or
[...todos].sort((a, b) => Date.parse(b.date) - Date.parse(a.date))
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With