Skip to content

Commit 194f157

Browse files
authored
#122 Handle cancel when "Type" changes (#177)
1 parent 0405b55 commit 194f157

File tree

4 files changed

+37
-3
lines changed

4 files changed

+37
-3
lines changed

Diff for: README.md

+1
Original file line numberDiff line numberDiff line change
@@ -854,6 +854,7 @@ This component is heavily inspired by [react-json-view](https://github.com./mac-s
854854
855855
- **1.24.0**:
856856
- Option to access (and render) the original node (and its key) within a [Custom Node](#custom-nodes) ([#180](https://github.com./CarlosNZ/json-edit-react/issues/180))
857+
- Cancelling edit after changing type correctly reverts to previous value ([#122](https://github.com./CarlosNZ/json-edit-react/issues/122))
857858
- **1.23.1**: Fix bug where you could collapse a node by clicking inside a "new key" input field [#175](https://github.com./CarlosNZ/json-edit-react/issues/175)
858859
- **1.23.0**:
859860
- Add `viewOnly` prop as a shorthand for restricting all editing [#168](https://github.com./CarlosNZ/json-edit-react/issues/168)

Diff for: src/CollectionNode.tsx

+10-1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ export const CollectionNode: React.FC<CollectionNodeProps> = (props) => {
3030
currentlyEditingElement,
3131
setCurrentlyEditingElement,
3232
areChildrenBeingEdited,
33+
previousValue,
34+
setPreviousValue,
3335
} = useTreeState()
3436
const {
3537
mainContainerRef,
@@ -99,7 +101,7 @@ export const CollectionNode: React.FC<CollectionNodeProps> = (props) => {
99101

100102
useEffect(() => {
101103
setStringifiedValue(jsonStringify(data))
102-
if (isEditing) setCurrentlyEditingElement(null)
104+
// if (isEditing) setCurrentlyEditingElement(null)
103105
}, [data])
104106

105107
useEffect(() => {
@@ -189,6 +191,7 @@ export const CollectionNode: React.FC<CollectionNodeProps> = (props) => {
189191
try {
190192
const value = jsonParse(stringifiedValue)
191193
setCurrentlyEditingElement(null)
194+
setPreviousValue(null)
192195
setError(null)
193196
if (JSON.stringify(value) === JSON.stringify(data)) return
194197
onEdit(value, path).then((error) => {
@@ -236,8 +239,13 @@ export const CollectionNode: React.FC<CollectionNodeProps> = (props) => {
236239

237240
const handleCancel = () => {
238241
setCurrentlyEditingElement(null)
242+
if (previousValue !== null) {
243+
onEdit(previousValue, path)
244+
return
245+
}
239246
setError(null)
240247
setStringifiedValue(jsonStringify(data))
248+
setPreviousValue(null)
241249
}
242250

243251
const showLabel = showArrayIndices || !isArray
@@ -366,6 +374,7 @@ export const CollectionNode: React.FC<CollectionNodeProps> = (props) => {
366374
canEdit
367375
? () => {
368376
hasBeenOpened.current = true
377+
setPreviousValue(null)
369378
setCurrentlyEditingElement(path)
370379
}
371380
: undefined

Diff for: src/ValueNodeWrapper.tsx

+14-1
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ export const ValueNodeWrapper: React.FC<ValueNodeProps> = (props) => {
5454
setPreviouslyEditedElement,
5555
tabDirection,
5656
setTabDirection,
57+
previousValue,
58+
setPreviousValue,
5759
} = useTreeState()
5860
const [value, setValue] = useState<typeof data | CollectionData>(
5961
// Bad things happen when you put a function into useState
@@ -178,6 +180,7 @@ export const ValueNodeWrapper: React.FC<ValueNodeProps> = (props) => {
178180

179181
const handleEdit = () => {
180182
setCurrentlyEditingElement(null)
183+
setPreviousValue(null)
181184
let newValue: JsonData
182185
switch (dataType) {
183186
case 'object':
@@ -202,7 +205,12 @@ export const ValueNodeWrapper: React.FC<ValueNodeProps> = (props) => {
202205

203206
const handleCancel = () => {
204207
setCurrentlyEditingElement(null)
208+
if (previousValue !== null) {
209+
onEdit(previousValue, path)
210+
return
211+
}
205212
setValue(data)
213+
setPreviousValue(null)
206214
}
207215

208216
const handleDelete = () => {
@@ -322,7 +330,12 @@ export const ValueNodeWrapper: React.FC<ValueNodeProps> = (props) => {
322330
showEditButtons && (
323331
<EditButtons
324332
startEdit={
325-
canEdit ? () => setCurrentlyEditingElement(path, handleCancel) : undefined
333+
canEdit
334+
? () => {
335+
setPreviousValue(value)
336+
setCurrentlyEditingElement(path, handleCancel)
337+
}
338+
: undefined
326339
}
327340
handleDelete={canDelete ? handleDelete : undefined}
328341
enableClipboard={enableClipboard}

Diff for: src/contexts/TreeStateProvider.tsx

+12-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*/
99

1010
import React, { createContext, useContext, useRef, useState } from 'react'
11-
import { type TabDirection, type CollectionKey } from '../types'
11+
import { type TabDirection, type CollectionKey, type JsonData } from '../types'
1212
import { toPathString } from '../helpers'
1313

1414
interface CollapseAllState {
@@ -37,6 +37,8 @@ interface TreeStateContext {
3737
setDragSource: (newState: DragSource) => void
3838
tabDirection: TabDirection
3939
setTabDirection: (dir: TabDirection) => void
40+
previousValue: JsonData | null
41+
setPreviousValue: (value: JsonData | null) => void
4042
}
4143
const initialContext: TreeStateContext = {
4244
collapseState: null,
@@ -51,13 +53,20 @@ const initialContext: TreeStateContext = {
5153
setDragSource: () => {},
5254
tabDirection: 'next',
5355
setTabDirection: () => {},
56+
previousValue: null,
57+
setPreviousValue: () => {},
5458
}
5559

5660
const TreeStateProviderContext = createContext(initialContext)
5761

5862
export const TreeStateProvider = ({ children }: { children: React.ReactNode }) => {
5963
const [collapseState, setCollapseState] = useState<CollapseAllState | null>(null)
6064
const [currentlyEditingElement, setCurrentlyEditingElement] = useState<string | null>(null)
65+
66+
// This value holds the "previous" value when user changes type. Because
67+
// changing data type causes a proper data update, cancelling afterwards
68+
// doesn't revert to the previous type. This value allows us to do that.
69+
const [previousValue, setPreviousValue] = useState<JsonData | null>(null)
6170
const [dragSource, setDragSource] = useState<DragSource>({
6271
path: null,
6372
pathString: null,
@@ -130,6 +139,8 @@ export const TreeStateProvider = ({ children }: { children: React.ReactNode }) =
130139
setTabDirection: (dir: TabDirection) => {
131140
tabDirection.current = dir
132141
},
142+
previousValue,
143+
setPreviousValue,
133144
// Drag-n-drop
134145
dragSource,
135146
setDragSource,

0 commit comments

Comments
 (0)