Get error after copy object

None, really.

Do I understand correctly that you need to update the diagram.model first, and not the redux store? Will the Store update itself, automatically or not?

Not exactly – GoJS has no knowledge of any data store or of React.

But the Model does need to be updated if you want to see any updated Nodes and Links in the Diagram.

The error persists until the method Model.mergeNodeDataArray is used.
When copying an object, the value of its location is saved. Even when moving, the location value does not change. The location value starts changing for the object after I change one of its properties. That is, when objects cease to be equal in deep comparison (not by reference but by to property values).
Studio_Project
Studio_Project(1)

to binding location I use

makeTwoWaySubBinding('location', 'location', 'diagramSettings', go.Point.parse, go.Point.stringify),
function makeTwoWaySubBinding(targetname, sourcename, objectName, conversion, backconversion, isUpdateNode) {
  const bind = new go.Binding(targetname, objectName);
  bind.mode = go.Binding.TwoWay;
  bind.converter = (diagramSettings, target) => {
    const value = diagramSettings[sourcename];
    if (value === undefined) return target[targetname];
    return (typeof conversion === 'function') ? conversion(value, target) : value;
  };
  bind.backConverter = (value, data, model) => {
    const objectData = data[objectName];
    if (model) {
      model.setDataProperty(objectData, sourcename, (typeof backconversion === 'function')
        ? backconversion(value, objectData, model)
        : value);
      if (isUpdateNode) {
        model.updateTargetBindings(data);
      }
    } else {
      objectData[sourcename] = (typeof backconversion === 'function') ? backconversion(value, objectData, model) : value;
    }
    return objectData;
  };
  return bind;
}

node template

const ImageNodeTemplate = (settings) => {
  const { handlersClickByImageNode } = settings;
  const { click, contextClick } = handlersClickByImageNode;

  return $(
    go.Node,
    'Vertical',
    {
      click,
      contextClick,
      isHighlighted: true,
      locationSpot: go.Spot.Center, // the location is the center of the Shape
      locationObjectName: 'SHAPE',
      selectionAdorned: false, // no selection handle when selected
      resizable: true,
      resizeObjectName: 'SHAPE', // user can resize the Shape
      selectionObjectName: 'SHAPE',
      rotatable: false,
      zOrder: 4,
      rotateObjectName: 'SHAPE', // rotate the Shape without rotating the label
      // eslint-disable-next-line no-bitwise
      layoutConditions: go.Part.LayoutStandard & ~go.Part.LayoutNodeSized,
    },
    new go.Binding('layerName', 'isHighlighted', ((h) => (h ? 'Foreground' : ''))).ofObject(),
    makeTwoWaySubBinding('location', 'location', 'diagramSettings', go.Point.parse, go.Point.stringify),
    makeTwoWaySubBinding('zOrder', 'zOrder', 'graphSettings'),
    $(
      go.Panel,
      'Auto',
      $(
        go.Shape,
        {
          name: 'SHAPE',
          strokeWidth: 3,
          fill: 'transparent',
          click: shapeClicked,
          opacity: 1,
          width: IMAGE_NODE_CONFIG.width,
          height: IMAGE_NODE_CONFIG.height,
        },
        new go.Binding('stroke', 'graphSettings', ObjectExtractor.getStrokeColor),
        new go.Binding('strokeWidth', 'graphSettings', ObjectExtractor.getStrokeWidth),
        new go.Binding('strokeDashArray', 'graphSettings', ObjectExtractor.isDashedGroupStroke),
        makeTwoWaySubBinding('desiredSize', 'sizePicture', 'diagramSettings', go.Size.parse, go.Size.stringify, true),
      ),
      $(
        go.Picture,
        {
          cursor: 'move',
          margin: 3,
          sourceCrossOrigin() {
            return 'anonymous';
          },
          // name: 'sizePicture',
          // click: shapeClicked,
          width: 50,
          height: 50,
        },
        makeTwoWaySubBinding('desiredSize', 'sizePicture', 'diagramSettings', go.Size.parse, go.Size.stringify),
        new go.Binding('source', 'source'),
      ),
    ),
  );
};

GoJS models hold data that are meant to be modified/mutated. This was required in the original design for efficiency reasons.

Are you saying that when the user moves a node, the value of node.data.diagramSettings.location does not change? If so, that sounds like a problem with the back-conversion function.

At the end of each transaction and each undo or redo there should be an updating of the underlying data store by copying any modified data.

node.data.diagramSettings.location is changed but change all objects. I change location one object, location will change in its copies.

Oh, so the diagramSettings Object is being shared by multiple node data objects? That’s not what you want.

Presumably you make sure there are separate diagramSettings Objects for each node data object when you create or update the model. That means the only likely problem is that when the user creates a new node or a copy of an existing node, the copied node data object is sharing the reference to the same diagramSettings object. You can fix that by providing your own data copying function, as the value of Model.copyNodeDataFunction. You’ll need to set that property on each instance of Model that you see, whether you create it programmatically or get it from a call to Model.fromJson.

Are there any examples using Model.copyNodeDataFunction?

Didn’t you get the code from Binding data sub-properties ?

I have not code.

The code that you posted in this topic seems to have been copied from that sample: Binding data sub-properties
As always, the complete source code is in the page itself.

Thank you, Walter