diff --git a/src/operations.js b/src/operations.js index b0bcd9e..aeb79e0 100644 --- a/src/operations.js +++ b/src/operations.js @@ -1,6 +1,4 @@ -import first from 'lodash/first' -import initial from 'lodash/initial' -import last from 'lodash/last' +import { first, initial, last, pickBy } from 'lodash-es' import { getIn } from './utils/immutabilityHelpers' import { compileJSONPointer } from './utils/jsonPointer' import { findUniqueName } from './utils/stringUtils' @@ -149,13 +147,18 @@ export function replace (json, paths, values, nextKeys) { // TODO: find a bette ] } else { // parent is Object + // if we're going to replace an existing object with key "a" with a new + // key "a", we must not create a new unique name "a (copy)". + const removeKeys = new Set(paths.map(path => last(path))) + const parentWithoutRemovedKeys = pickBy(parent, (value, key) => !removeKeys.has(key)) + return [ // remove operations ...removeAll(paths), // insert operations ...values.map(entry => { - const newProp = findUniqueName(entry.key, parent) + const newProp = findUniqueName(entry.key, parentWithoutRemovedKeys) return { op: 'add', path: compileJSONPointer(parentPath.concat(newProp)), diff --git a/src/utils/updateProps.js b/src/utils/updateProps.js index 87e2d25..369d10f 100644 --- a/src/utils/updateProps.js +++ b/src/utils/updateProps.js @@ -78,17 +78,21 @@ export function patchProps (state, operations) { } if (operation.op === 'add') { - const path = parseJSONPointer(operation.path) - const parentPath = initial(path) + const pathTo = parseJSONPointer(operation.path) + const parentPath = initial(pathTo) + const key = last(pathTo) const props = getIn(updatedState, parentPath.concat(STATE_PROPS)) if (props) { - const newProp = { - id: uniqueId(), - key: last(path) - } - const updatedProps = insertAt(props, [props.length], newProp) + const index = props.findIndex(item => item.key === key) + if (index === -1) { + const newProp = { + id: uniqueId(), + key + } + const updatedProps = insertAt(props, [props.length], newProp) - updatedState = setIn(updatedState, parentPath.concat([STATE_PROPS]), updatedProps) + updatedState = setIn(updatedState, parentPath.concat([STATE_PROPS]), updatedProps) + } } } })