← Wszystkie zadaniaReact · Senior

Undo i redo

Napisz hook useHistory(initial) - stan z historią zmian. Zwraca { value, set, undo, redo, canUndo, canRedo }.

set(v) ustawia v jako bieżącą wartość i zapamiętuje poprzednią. undo() przywraca poprzednią wartość, redo() - cofniętą. Nowy set po undo usuwa gałąź do redo. undo i redo bez historii nic nie robią. Kilka wywołań set z rzędu w jednym handlerze musi zostać zapisanych.

Testy (6)

  1. const { result } = renderHook(() => useHistory('a'));
    expect(result.current.value).toBe('a');
    expect(result.current.canUndo).toBe(false);
    expect(result.current.canRedo).toBe(false);
  2. const { result } = renderHook(() => useHistory(0));
    act(() => result.current.set(1));
    act(() => result.current.set(2));
    act(() => result.current.undo());
    expect(result.current.value).toBe(1);
    act(() => result.current.undo());
    expect(result.current.value).toBe(0);
    expect(result.current.canUndo).toBe(false);
  3. const { result } = renderHook(() => useHistory(0));
    act(() => result.current.set(1));
    act(() => result.current.undo());
    expect(result.current.canRedo).toBe(true);
    act(() => result.current.redo());
    expect(result.current.value).toBe(1);
    expect(result.current.canRedo).toBe(false);
  4. const { result } = renderHook(() => useHistory(0));
    act(() => result.current.set(1));
    act(() => result.current.set(2));
    act(() => result.current.undo());
    act(() => result.current.set(3));
    expect(result.current.value).toBe(3);
    expect(result.current.canRedo).toBe(false);
    act(() => result.current.undo());
    expect(result.current.value).toBe(1);
  5. const { result } = renderHook(() => useHistory('x'));
    act(() => result.current.undo());
    act(() => result.current.redo());
    expect(result.current.value).toBe('x');
  6. const { result } = renderHook(() => useHistory(0));
    act(() => {
      result.current.set(1);
      result.current.set(2);
    });
    act(() => result.current.undo());
    expect(result.current.value).toBe(1);