JSFiddle - React, Tailwind, and code Playground

HTML

<script src="http://momentjs.com/downloads/moment.min.js"></script>
<div ng-controller="TasksCtrl">
    <button ng-click="refresh()">Refresh Tasks</button> Click this to feel the delay, then change the HTML on the left to see the no-delay version that uses "track by"
    <button ng-click="add()">add</button>
     <button ng-click="update()">update</button> 
      <button ng-click="updateId()">updateId</button>
       <button ng-click="remove()">remove</button>
     <button ng-click="updateNested()">updateNested</button> 
     <button ng-click="updateNestedArray()">updateNestedArray</button> 

<ul class="tasks">
        <!-- Try commenting the line below and uncommenting the other -->
        <li ng-repeat="task in tasks" task="task" class="task">123</li>
        <!--<li ng-repeat="task in tasks track by task.id" task="task" class="task"></li>-->
    </ul>
</div>

CSS

.tasks {
    max-height: 19em;
    overflow-y: scroll;
    border: 3px solid #ccc;
    list-style: none;
    padding: 0;
}

.tasks .task {
    padding: 0.5em;
    border: 1px solid #007aff;
}

.tasks .task .time {
    color: #8f8f8f;
    font-size: 0.7em;
}

JavaScript

angular.module('myApp', [])
.controller('TasksCtrl', function($scope) {
    var date = new Date().toISOString();
    $scope.tasks = [];
    for (var i = 1; i < 301; i++) {
        $scope.tasks.push({
            id: i,
            title: 'Task ' + i, 
            date: date,
            nested: {name: 'N'+i,value: i},
            nestedArray: [{name: 'first'}]
        });
    }
    $scope.add = function() {
      id = $scope.tasks[0].id-1;
      $scope.tasks.unshift({
            id: id,
            title: 'Task 0', 
            date: 'a',
            nested: {name: 'N'+id,value: id},
            nestedArray: [{name: 'first'}]
        });
    }
     $scope.remove = function() {
            $scope.tasks.shift();
    }
    $scope.update = function() {
            $scope.tasks[0].title = $scope.tasks[0].title + 'a';
    }
    $scope.updateId = function() {
            $scope.tasks[0].id = $scope.tasks[0].id - 1;
    }
    $scope.updateNested = function() {
            $scope.tasks[0].nested.name =       $scope.tasks[0].nested.name + 'a';
    }
        $scope.updateNestedArray = function() {
            $scope.tasks[0].nestedArray[0].name =       $scope.tasks[0].nestedArray[0].name + 'a';
    }
    $scope.refresh = function() {
        console.log("refreshing")
        $scope.tasks = angular.copy($scope.tasks);
    };
})
.directive('task', function() {
    return {
        scope: {
            task: '='
        },
        template: '{{ task.id }} {{ task.title }} <span class="time">({{ prettyTaskDate }})</span>{{ task.nested.name}} {{ task.nested.value}} {{ task.nestedArray[0].name }}',
        link: function(scope) {
            console.log('rendering', scope.task.id);
      
            scope.$watch('task.date', function() {
                scope.prettyTaskDate = scope.task.date;
            });
        }
    };
});