← All tasksReact · Senior

Unnecessary row renders

The code in the editor works, but every click on the counter re-renders every row of the list - you can check that with onRowRender, which a row calls on each of its renders.

Make a row render only when its own props change: clicking the counter must not render the rows, and removing one row must not render the others. Don't change the markup or the texts.

Tests (4)

  1. const onRowRender = fn();
    render(<App onRowRender={onRowRender} />);
    expect(onRowRender).toHaveBeenCalledTimes(3);
  2. const onRowRender = fn();
    render(<App onRowRender={onRowRender} />);
    fireEvent.click(screen.getByRole('button', { name: 'Clicked 0' }));
    fireEvent.click(screen.getByRole('button', { name: 'Clicked 1' }));
    expect(screen.getByRole('button', { name: 'Clicked 2' })).toBeTruthy();
    expect(onRowRender).toHaveBeenCalledTimes(3);
  3. const onRowRender = fn();
    render(<App onRowRender={onRowRender} />);
    fireEvent.click(screen.getByRole('button', { name: 'Remove b' }));
    expect(screen.getAllByTestId('row').map((row) => row.firstChild.textContent)).toEqual(['a', 'c']);
    expect(onRowRender).toHaveBeenCalledTimes(3);
  4. const onRowRender = fn();
    render(<App onRowRender={onRowRender} />);
    fireEvent.click(screen.getByRole('button', { name: 'Remove a' }));
    fireEvent.click(screen.getByRole('button', { name: 'Remove c' }));
    expect(screen.getAllByTestId('row').map((row) => row.firstChild.textContent)).toEqual(['b']);