I have a list of simple objects that I want to display, so I create components using *ngFor
. Every component has css hover effect that changes its background. When I change object's property in an immutable way (create new array with replaced one object) the background of the associated component often flickers.
List component:
import { Component, ChangeDetectionStrategy } from '@angular/core';
@Component({
selector: 'my-app',
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<list-item *ngFor="let item of items"
[item]="item"
(toggle)="onToggle(item)"
></list-item>
`,
})
export class AppComponent {
items = [
{ name: 'item1', toggled: false },
{ name: 'item2 ', toggled: true },
{ name: 'item3', toggled: false }
];
onToggle(item) {
const updatedItem = {
...item,
toggled: !item.toggled
};
this.items = this.items.map(item => item.name === updatedItem.name ? updatedItem : item);
}
}
List item component:
import { Component, Input, Output, EventEmitter, ChangeDetectionStrategy } from '@angular/core';
@Component({
selector: 'list-item',
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<div class="container">
<span>{{ item.name }}: {{ item.toggled }}</span>
<button (click)="toggle.emit()">Toggle!</button>
</div>
`,
styles: [`
.container {
width: 400px;
height: 50px;
border: 1px solid black;
display: flex;
padding: 20px;
justify-content: space-between;
align-items: center;
}
.container:hover {
background-color: yellow;
}
`]
})
export class ListItemComponent {
@Input() item: Item;
@Output() toggle: EventEmitter<void> = new EventEmitter<void>();
}
export interface Item {
name: string;
toggled: boolean;
}
Here is a demo: https://stackblitz.com/edit/angular-pmdjqu?embed=1&file=app/listItem.component.ts
How can I fix this problem? Is Angular broken or am I doing something wrong? Maybe Angular is not designed for immutable manipulations?
(In React such problem does not exist: https://stackblitz.com/edit/react-bdul7z?file=index.js )
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.