diff --git a/README.md b/README.md index ea1fa41..4eee143 100644 --- a/README.md +++ b/README.md @@ -1216,6 +1216,7 @@ This component is heavily inspired by [react-json-view](https://github.com/mac-s ## Changelog +- **1.26.1**: Fix bug when submitting with keyboard after switching to `null` type ([#194](https://github.com/CarlosNZ/json-edit-react/pull/194)) - **1.26.0**: - Handle non-standard data types (e.g. `undefined`, `BigInt`) when stringifying/parsing JSON - More custom components (See [library ReadMe](https://github.com/CarlosNZ/json-edit-react/blob/main/custom-component-library/README.md)) diff --git a/src/ValueNodes.tsx b/src/ValueNodes.tsx index 43a861e..c8e1387 100644 --- a/src/ValueNodes.tsx +++ b/src/ValueNodes.tsx @@ -256,6 +256,8 @@ export const BooleanValue: React.FC = ({ }) => { const { getStyles } = useTheme() + if (typeof value !== 'boolean') return null + return isEditing ? ( = ({ ) } -// A custom hook to add a keyboard listener to a component that does't have +// A custom hook to add a keyboard listener to a component that doesn't have // standard DOM keyboard behaviour (like inputs). Only used for the `null` // component here, but is exported for re-use with Custom Components if required export const useKeyboardListener = (isEditing: boolean, listener: (e: unknown) => void) => { const timer = useRef(undefined) + const currentListener = useRef(listener) + // Always update the ref to point to the latest listener useEffect(() => { - if (!isEditing) { - // The listener messes with other elements when switching rapidly (e.g. - // when "getNext" is called repeatedly on inaccessible elements), so we - // cancel the listener load before it even happens if this node gets - // switched from isEditing to not in less than 100ms - window.clearTimeout(timer.current) - return - } + currentListener.current = listener + }, [listener]) + + // Define our stable event handler function + const eventHandler = (e: unknown) => { + currentListener.current(e) + } + + useEffect(() => { + // The listener messes with other elements when switching rapidly (e.g. when + // "getNext" is called repeatedly on inaccessible elements), so we cancel + // the listener load before it even happens if this node gets switched from + // isEditing to not in less than 100ms + window.clearTimeout(timer.current) + + if (!isEditing) return + // Small delay to prevent registering keyboard input from previous element // if switched using "Tab" - timer.current = window.setTimeout(() => window.addEventListener('keydown', listener), 100) + timer.current = window.setTimeout(() => { + window.addEventListener('keydown', eventHandler) + }, 100) - return () => window.removeEventListener('keydown', listener) - }, [isEditing, listener]) + // Cleanup function + return () => { + window.clearTimeout(timer.current) + window.removeEventListener('keydown', eventHandler) + } + }, [isEditing]) } export const NullValue: React.FC = ({