← Усі задачіReact · Senior

Undo і redo

Напишіть хук useHistory(initial) - стан з історією змін. Він повертає { value, set, undo, redo, canUndo, canRedo }.

set(v) робить v поточним значенням і запам'ятовує попереднє. undo() повертає попереднє значення, redo() - скасоване. Новий set після undo стирає гілку для redo. undo і redo без історії нічого не роблять. Кілька set поспіль в одному обробнику мають записатися всі.

Тести (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);