Replies: 3 comments
-
@edmundhung Happy to create a repro if you have a sandbox I could use. However, the issue is fairly isolated. |
Beta Was this translation helpful? Give feedback.
0 replies
-
ah, after familiarizing more with the problem, I realized this is just a general issue with controlled components. I can write an abstraction that handles this, but shouldn't this be handled by |
Beta Was this translation helpful? Give feedback.
0 replies
-
import { type Reducer, useCallback, useReducer, useRef } from 'react';
type HistoryState<T> = {
canRedo: boolean;
canUndo: boolean;
clear: () => void;
redo: () => void;
set: (newPresent: T) => void;
state: T;
undo: () => void;
};
type ReducerAction<T> =
| {
initialPresent: T;
type: 'CLEAR';
}
| {
newPresent: T;
type: 'SET';
}
| {
type: 'UNDO';
}
| {
type: 'REDO';
};
const initialUseHistoryStateState = {
future: [],
past: [],
present: null,
};
type ReducerState<T> = {
future: T[];
past: T[];
present: T;
};
const stateReducer = <T>(
state: ReducerState<T>,
action: ReducerAction<T>,
): ReducerState<T> => {
const { past, present, future } = state;
if (action.type === 'UNDO') {
return {
future: [present, ...future],
past: past.slice(0, past.length - 1),
present: past[past.length - 1],
};
} else if (action.type === 'REDO') {
return {
future: future.slice(1),
past: [...past, present],
present: future[0],
};
} else if (action.type === 'SET') {
const { newPresent } = action;
if (action.newPresent === present) {
return state;
}
return {
future: [],
past: [...past, present],
present: newPresent,
};
} else if (action.type === 'CLEAR') {
return {
...initialUseHistoryStateState,
present: action.initialPresent,
};
} else {
throw new Error('Unsupported action type');
}
};
export const useHistoryState = <T>(initialPresent: T): HistoryState<T> => {
const initialPresentRef = useRef(initialPresent);
const [state, dispatch] = useReducer<
Reducer<ReducerState<T>, ReducerAction<T>>
>(stateReducer, {
...initialUseHistoryStateState,
present: initialPresentRef.current,
});
const canUndo = state.past.length !== 0;
const canRedo = state.future.length !== 0;
const undo = useCallback(() => {
if (canUndo) {
dispatch({ type: 'UNDO' });
}
}, [canUndo]);
const redo = useCallback(() => {
if (canRedo) {
dispatch({ type: 'REDO' });
}
}, [canRedo]);
const set = useCallback<(newPresent: T) => void>(
(newPresent) => dispatch({ newPresent, type: 'SET' }),
[],
);
const clear = useCallback(
() =>
dispatch({ initialPresent: initialPresentRef.current, type: 'CLEAR' }),
[],
);
return { canRedo, canUndo, clear, redo, set, state: state.present, undo };
}; Ripped out of https://github.com/uidotdev/usehooks |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
Describe the bug and the expected behavior
I would expect that I can undo after pasting.
Conform version
v1.1.5
Steps to Reproduce the Bug or Issue
The necessary code is just:
What browsers are you seeing the problem on?
Chrome
Screenshots or Videos
No response
Additional context
It seems that when
onPaste
is added,undo
(cmd + z) starts doing something weird that's not undoing the last paste.Beta Was this translation helpful? Give feedback.
All reactions