Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update blocklyworkspace from external events via new props #127

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

hcientist
Copy link

  1. New Features:
    1. adds props updateXml and updateJson, which if passed to the component/hook will result in the blockly workspace rerendering when the values of either of these new properties is changed. ( fixes add prop for updating blocks from external events #125 )
    2. adds documentation of these props to README as well as demonstrations of their use to the dev demo (via bi-directional editing, edit the json or xml in the newly added textareas, and see the blockly workspace update. warning: the json or xml should be valid. for my use case i won't actually expose a text editor, but rather will be editing via another component that should already validate before updating this prop).
  2. Fixes:
    1. minor typos in README and useBlocklyWorkspace
    2. add missing docs to README[1,2]

Copy link
Owner

@nbudin nbudin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @hcientist! I'm a little confused by what the updateXml and updateJson options are doing - it looks like they're static strings which are checked for changes via the useEffect hook's dependencies. I'm worried that it might be too easy for a user to accidentally cause these references to change by accident on every render.

I'm wondering if, instead, we could have useBlocklyWorkspace return some callback functions that do the same thing - i.e., in addition to workspace, xml, and json, it could also return updateXml and updateJson functions that components could call to manually trigger updates. Would that change work for your use case?

@@ -57,7 +78,7 @@ const useBlocklyWorkspace = ({
json: object | null;
} => {
// onImportError replaces onImportXmlError
// This is done for not breaking the signature until depreaction
// This is done for not breaking the signature until deprecation
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

whoops, thanks for the spelling fix! ❤️

@hcientist
Copy link
Author

hcientist commented Mar 10, 2025

@nbudin thanks for all your work on this project and for considering my PR!

I think anything is fine here and defer to your experience with react, blockly, and react-blockly.
I just need a way to request react-blockly (either the component or the hook) update the internal workspace with the state I provide.

With your proposal, my code that currently:

  1. (is a component that) has a state variable created via the useState hook
  2. passes that var into BlocklyWorkspace via the proposed updateJson prop (so that var is only changed when I call the corresponding setter from the useState hook)

Would instead:

  1. duplicate the source of the BlocklyWorkspace component (so that I get all the refs and event handlers implemented there)
  2. make an adapter for my aforementioned setter (created from our own useState) that would also invoke the proposed updateJson in addition to invoking the useState setter?

I am working to update the dev-index.tsx in my fork to try to clarify this because I'm not sure how anyone could parse what I just typed 😆. will update

@nbudin
Copy link
Owner

nbudin commented Mar 10, 2025

I don't think you'd necessarily need to change very much about your existing component (although I'd have to see it to say for sure). What I'm thinking is that if you wanted to track the JSON/XML as a piece of state in your component, you could do something like this:

const { updateJson } = useBlocklyWorkspace(); // plus whatever else you're doing here
const [json, setJson] = useState('');

const onJsonChange = (event) => {
  setJson(event.target.value);
  updateJson(event.target.value);
};

return <textarea value={json} onChange={onJsonChange} />;

Does that make sense?

@hcientist
Copy link
Author

Ok, yes. Thanks for the clarification. In our use case we are using react-blockly to:

  1. render the blockly editor (and therefore we use the BlockWorkspace component rather than the useBlocklyWorkspace hook)
  2. invoke our onJsonChange so that we are notified if the user directly interacts with the blockly editor provided by BlockWorkspace
  3. and we would like to also update the blockly workspace when changes happen outside of react-blockly

So if it makes more sense for this project to have the props as callbacks passed via props to the hook, rather than as props on the component, that is totally fine.

For our use case we need both the dom element and the onJsonChange (both are already manged in the BlockWorkspace component), so we will end up with a few redundant lines (most of the code that's already in the BlockWorkspace component) in our component that use the hook rather than the component.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

add prop for updating blocks from external events
2 participants