{"action":"created","issue":{"url":"https://api.github.com/repos/dojo/app/issues/80","repository_url":"https://api.github.com/repos/dojo/app","labels_url":"https://api.github.com/repos/dojo/app/issues/80/labels{/name}","comments_url":"https://api.github.com/repos/dojo/app/issues/80/comments","events_url":"https://api.github.com/repos/dojo/app/issues/80/events","html_url":"https://github.com/dojo/app/issues/80","id":182913114,"number":80,"title":"Race condition with widget creation by type","user":{"login":"agubler","id":1982678,"avatar_url":"https://avatars.githubusercontent.com/u/1982678?v=3","gravatar_id":"","url":"https://api.github.com/users/agubler","html_url":"https://github.com/agubler","followers_url":"https://api.github.com/users/agubler/followers","following_url":"https://api.github.com/users/agubler/following{/other_user}","gists_url":"https://api.github.com/users/agubler/gists{/gist_id}","starred_url":"https://api.github.com/users/agubler/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/agubler/subscriptions","organizations_url":"https://api.github.com/users/agubler/orgs","repos_url":"https://api.github.com/users/agubler/repos","events_url":"https://api.github.com/users/agubler/events{/privacy}","received_events_url":"https://api.github.com/users/agubler/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":4,"created_at":"2016-10-13T21:53:45Z","updated_at":"2016-10-14T11:30:06Z","closed_at":null,"body":"When `getWidget` is called for an `id` that is dynamically created using the `.type` from the associated to the state entry. If `getWidget` is called again (with the same id) before the widget has actually been factoried and registered then `app` will try and create the widget again. \r\n\r\nThis causes a failure when attempting to register the (duplicate) widget as an entry for that `id` already exists in the registry.\r\n\r\n**Version and Environment:**\r\n\r\nDojo2 version: latest\r\n\r\n**Code**\r\n\r\n```js\r\nimport createApp from 'dojo-app/createApp';\r\nimport createMemoryStore from 'dojo-stores/createMemoryStore';\r\n\r\nimport createWidget from 'dojo-widgets/createWidget';\r\nimport createPanel from 'dojo-widgets/createPanel';\r\n\r\nconst widgetStore = createMemoryStore<any>({\r\n\tdata: [\r\n\t\t{\r\n\t\t\tid: 'container'\r\n\t\t}\r\n\t]\r\n});\r\n\r\nconst app = createApp({ defaultWidgetStore: widgetStore });\r\n\r\napp.loadDefinition({\r\n\twidgets: [\r\n\t\t{\r\n\t\t\tid: 'container',\r\n\t\t\tfactory: createPanel\r\n\t\t}\r\n\t],\r\n\tcustomElements: [\r\n\t\t{\r\n\t\t\tname: 'dynamically-created-child',\r\n\t\t\tfactory: createWidget\r\n\t\t}\r\n\t]\r\n});\r\n\r\napp.realize(document.body)\r\n\t.then(() => {\r\n\t\tconst children: string[] = [];\r\n\t\tfor (let i = 0; i < 10; i++) {\r\n\t\t\tconst id = `${i}`;\r\n\t\t\tchildren.push(id);\r\n\t\t\twidgetStore\r\n\t\t\t\t.put({id, type: 'dynamically-created-child', label: 'This is label number ' + i})\r\n\t\t\t\t.patch({id: 'container', children});\r\n\r\n\t\t}\r\n\t});\r\n\r\n```\r\n\r\n**Expected behavior:**\r\n\r\nRender 10 children items:\r\n\r\n```\r\nThis is label number 0\r\nThis is label number 1\r\nThis is label number 2\r\nThis is label number 3\r\nThis is label number 4\r\nThis is label number 5\r\nThis is label number 6\r\nThis is label number 7\r\nThis is label number 8\r\nThis is label number 9\r\n```\r\n\r\n**Actual behavior:** \r\n\r\nNo children render.\r\n"},"comment":{"url":"https://api.github.com/repos/dojo/app/issues/comments/253775531","html_url":"https://github.com/dojo/app/issues/80#issuecomment-253775531","issue_url":"https://api.github.com/repos/dojo/app/issues/80","id":253775531,"user":{"login":"novemberborn","id":33538,"avatar_url":"https://avatars.githubusercontent.com/u/33538?v=3","gravatar_id":"","url":"https://api.github.com/users/novemberborn","html_url":"https://github.com/novemberborn","followers_url":"https://api.github.com/users/novemberborn/followers","following_url":"https://api.github.com/users/novemberborn/following{/other_user}","gists_url":"https://api.github.com/users/novemberborn/gists{/gist_id}","starred_url":"https://api.github.com/users/novemberborn/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/novemberborn/subscriptions","organizations_url":"https://api.github.com/users/novemberborn/orgs","repos_url":"https://api.github.com/users/novemberborn/repos","events_url":"https://api.github.com/users/novemberborn/events{/privacy}","received_events_url":"https://api.github.com/users/novemberborn/received_events","type":"User","site_admin":false},"created_at":"2016-10-14T11:30:06Z","updated_at":"2016-10-14T11:30:06Z","body":"> Or do you think we could keep a state internally that app was in the process of creating the widget for that id and skip the creation all together?\r\n\r\nThat's effectively what the factories do. They register a new factory which returns the same promise.\r\n\r\nConceivably we could register a widget factory for the given `id` once we determine we can create the widget using its `type`. That always takes precedence, so future calls will invoke that factory to get a promise for the widget instance."}}
{"actor":{"display_login":"novemberborn"}}