{"action":"closed","issue":{"url":"https://api.github.com/repos/facebook/react/issues/1923","repository_url":"https://api.github.com/repos/facebook/react","labels_url":"https://api.github.com/repos/facebook/react/issues/1923/labels{/name}","comments_url":"https://api.github.com/repos/facebook/react/issues/1923/comments","events_url":"https://api.github.com/repos/facebook/react/issues/1923/events","html_url":"https://github.com/facebook/react/issues/1923","id":38654181,"number":1923,"title":"React.addons.update should return the input object when we replace a value by itself","user":{"login":"slorber","id":749374,"avatar_url":"https://avatars.githubusercontent.com/u/749374?v=3","gravatar_id":"","url":"https://api.github.com/users/slorber","html_url":"https://github.com/slorber","followers_url":"https://api.github.com/users/slorber/followers","following_url":"https://api.github.com/users/slorber/following{/other_user}","gists_url":"https://api.github.com/users/slorber/gists{/gist_id}","starred_url":"https://api.github.com/users/slorber/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/slorber/subscriptions","organizations_url":"https://api.github.com/users/slorber/orgs","repos_url":"https://api.github.com/users/slorber/repos","events_url":"https://api.github.com/users/slorber/events{/privacy}","received_events_url":"https://api.github.com/users/slorber/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/facebook/react/labels/Component:%20Addons%20/%20Update","name":"Component: Addons / Update","color":"fad8c7"}],"state":"closed","locked":false,"assignee":null,"milestone":null,"comments":7,"created_at":"2014-07-24T17:22:38Z","updated_at":"2016-04-01T02:36:15Z","closed_at":"2016-04-01T02:36:15Z","body":"This code shows the problem\r\n\r\n```\r\nvar root = {\r\n    prop: \"propValue\",\r\n    nested: {\r\n        nestedProp: \"nestedPropValue\"\r\n    }\r\n}\r\n\r\nvar rootCopy = React.addons.update(root,{\r\n    nested: { $set: root.nested }\r\n});\r\n\r\nvar rootCopy2 = React.addons.update(root,{\r\n    nested: { nestedProp : {$set: root.nested} }\r\n});\r\n\r\nconsole.debug(\"root === rootCopy\",root === rootCopy);\r\nconsole.debug(\"root.prop === rootCopy.prop\",root.prop === rootCopy.prop);\r\nconsole.debug(\"root.nested === rootCopy.nested\",root.nested === rootCopy.nested);\r\n\r\nconsole.debug(\"root === rootCopy2\",root === rootCopy);\r\nconsole.debug(\"root.prop === rootCopy2.prop\",root.prop === rootCopy2.prop);\r\nconsole.debug(\"root.nested === rootCopy2.nested\",root.nested === rootCopy2.nested);\r\n```\r\n\r\n```\r\nroot === rootCopy false app.js:46\r\nroot.prop === rootCopy.prop true app.js:47\r\nroot.nested === rootCopy.nested true app.js:48\r\n\r\nroot === rootCopy2 false app.js:50\r\nroot.prop === rootCopy2.prop true app.js:51\r\nroot.nested === rootCopy2.nested false \r\n```\r\n\r\nI woould expect all these equality to be true.\r\n\r\nI think this is the point of immutability/structural sharing to not create useless objects when their inner properties are equally the same.\r\n\r\n```\r\nvar object = {}\r\nobject = React.addons.update(object, { prop: { $set: propValue} });\r\nobject = React.addons.update(object, { prop: { $set: propValue} });\r\n```\r\nOn the 2nd call, it makes sense that the object returned is the object from the arguments.\r\n\r\n\r\nEnsuring this can help to avoid unexpected behavior in shouldComponentUpdate and prevent some useless renderings that I have encountered (when user clicks twice on the same menu element for exemple)"}}