blocks are injected twice
randrei12 opened this issue · comments
During react renders the blocks' xml ends up injecting twice.
const { loaded, project, updateProject } = useProject(); //here is stored the workspace (into data.blocks property)
const blocklyRef = useRef(null);
const { xml, workspace } = useBlocklyWorkspace({
ref: blocklyRef,
toolboxConfiguration: toolbox,
initialXml: '',
workspaceConfiguration: { zoom: { controls: true, wheel: true, startScale: 1, maxScale: 3, minScale: 0.3, scaleSpeed: 1.2 }, theme },
onWorkspaceChange: (workspace) => {
if (loaded) {
console.log(xml);
}
}
});
useEffect(() => {
if (loaded) {
Blockly.serialization.workspaces.load(JSON.parse(project.data.blocks), Blockly.getMainWorkspace());
}
}, [loaded]);
return (
<div id="blockly" ref={blocklyRef}></div>
);
As you can see from the following image, the xml ends up doubling each block
Thanks in advance!
Hi @randrei12! I'm not sure that this log actually indicates an issue. onWorkspaceChange
can be called many times; there is no guarantee that it won't be called multiple times with the same data even for just one change. This is usually not a problem, because typically what you'd be doing with the data passed into that function is to pass it into a state setter, and that's fine because setting the state to the same thing it's already set to won't do anything.
I do see that in each invocation of console.log
in your screenshot, there don't appear to be duplicated blocks - each block has a unique ID within each log line. It's just that the log lines themselves are coming multiple times, because the onWorkspaceChange
function is called more often than you expect.
Does this make sense, or am I missing a different issue?
Hello, @nbudin and thanks for your help! The logs are invoked all at once, at start. As you can see, the xml has only one block at the beggining (as it should be) then it suddenly ends up having another block, which is a clone of the first one. I don't understand why it ends up cloning the first block. The following json is loaded by the workspace:
{
"blocks": {
"languageVersion": 0,
"blocks": [
{
"type": "go_to",
"id": "k3UocM0qeyD#DYnrCrh+",
"x": 36,
"y": 36,
"inputs": {
"LOCATION": {
"shadow": {
"type": "text",
"id": "I_H@.8]?S=N$vyd#FDQX",
"fields": {
"TEXT": ""
}
}
}
}
}
]
}
}
As you can see, there's only one block, not two.
Interesting. I think this can happen if Blockly.serialization.workspaces.load
is invoked twice (in other words, it doesn't clear out the existing contents of the workspace). I'm not sure exactly why that would be happening, but if loaded
can change multiple times, the useEffect
could run multiple times.
Without seeing the contents of the useProject
hook, it's hard to say when and how loaded
might change.
Whoa, super weird!
Would you mind sending me a copy of your code so I can try it out on my machine? If you don't feel comfortable sharing it publicly, you can email it to me at natbudin@gmail.com.
Hello @nbudin! The problem is not with my project, as I was able to recreate the problem in a sandbox (Link). I strongly believe the problem is with workspace parse, which triggers multiple domToWorkspace function runs.
Ok, thanks @randrei12! I'll be out of town on a trip until Tuesday, so I probably won't be able to debug further until then. If you come up with a workaround or a patch, please let me know and I'll try to get something out! Otherwise, I'll be able to look at this in depth on Tuesday.
Ok, I'll try to debug further and find the root cause. Thanks for your help!
I see @randrei12 closed the issue but, FWIW, I'm seeing a similar issue where the first block I drag into the workspace is duplicated. However, subsequent drag operations do not duplicate the block.
Here is are my workspace params. Of note, the OnWorkspaceChange function is completely empty and this still occurs:
function MyBlocklyEditor() {
const [xml, setXml] = useState("");
return (
<BlocklyWorkspace
className="width-100" // you can use whatever classes are appropriate for your app's CSS
toolboxConfiguration={theToolbox} // this must be a JSON toolbox definition
workspaceConfiguration={
{
grid: {
spacing: 20,
length: 3,
colour: "#000000",
snap: true,
},
}
}
// initialXml={ConfigFiles.INITIAL_XML}
initialXml={xml}
onXmlChange={setXml}
onWorkspaceChange={workspaceDidChange}
/>
)
}
version in use
"blockly": "^9.0.0", "react": "^18.2.0", "react-blockly": "^7.1.0",
Visualization of this "double dragon" situation I'm seeing
https://user-images.githubusercontent.com/14134766/222878470-1802c886-c147-434a-972f-8fa86053feeb.mp4