Solidify new Sandcastle React structure
Description
When I originally threw this together for the hackathon I tried to reuse a lot of the existing code for current sandcastle to speed up development. This meant a lot of the logic was very "imperative" oriented and was not playing nicely with React. This worked fine for a while but started to really get in the way in #12631, specifically with multiple loading methods.
This PR restructures the application to be much more "React" oriented
- State is now much more actively maintained and controlled
- This prevents all the direct monaco editor
getValueandsetValueaccess I was doing before
- This prevents all the direct monaco editor
- The
iframewrapper logic has been pulled out to it's ownBucket- "Running" a sandcastle is now controlled by changing the
propson theBucketusing thecomittedCodeandrunNumberstate
- "Running" a sandcastle is now controlled by changing the
- Unified into a single Monaco
Editorinstance using multiple Models. It is now a controlled component and the contents are tracked and stored in state
This code builds off of #12631 and should be merged after that
Issue number and link
Part of #12566
Testing plan
- Run sandcastle using
npm run devfrom insidepackages/sandcastle - Load sandcastle at
http://localhost:5173/ - Make sure that:
- Loading from a share URL works and has the correct code and viewer state on first load
- Clicking gallery items loads the correct code, refreshes the viewer and updates the URL
- Clicking
Newresets both the JS and HTML code, refreshes the viewer and updates the URL - Swapping between JS and HTML works as expected
- The
Add buttonand others work but do not refresh the viewer untilRunis clicked - Hitting
F8while focusing inside the code actually reloads the viewer - Clicking
RunorF8multiple times in a row with no code changes refreshes the viewer every time- This is specifically why I added the
runNumberstate, this is a workflow that must work
- This is specifically why I added the
Author checklist
- [ ] I have submitted a Contributor License Agreement
- [ ] I have added my name to
CONTRIBUTORS.md - [ ] I have updated
CHANGES.mdwith a short summary of my change - [ ] I have added or updated unit tests to ensure consistent code coverage
- [ ] I have updated the inline documentation, and included code examples where relevant
- [ ] I have performed a self-review of my code
Thank you for the pull request, @jjspace!
:white_check_mark: We can confirm we have a CLA on file for you.
@aruniverse or maybe @angrycat9000, would one (or both?) of you have some free time to take a look at this PR and review the React usage? No need to analyze the Sandcastle structure or "business logic". I haven't done much React dev in a while and I'm trying to get used to the mental paradigms again. I just want to make sure I'm not doing anything really horrible.
Did a read through of the code. The sandcastle v2 link didn't work for me so I wasn't sure how to run it.
The DOM manipulation in Bucket raised a red flag for me. Would have expected that everything is written in React and not setting innerHTML. If we do need to do the direct manipulation then I would clearly document why it is needed.
Otherwise looks pretty standard.
Would also recommend breaking stuff down into smaller components for readability. The App component is a bit hefty and has a lot of logic that could probably be better isolated. Eg the editor set/teardown could be in its own Editor component. The gallery loading could be in its own component that uses "onGallerySelected" to communicate back to the main app.
Thanks for the review @angrycat9000
The DOM manipulation in Bucket raised a red flag for me. Would have expected that everything is written in React and not setting innerHTML. If we do need to do the direct manipulation then I would clearly document why it is needed.
The only DOM manipulation we're still doing is to modify/control the contents of the iframe, ie the "bucket", to load the sandcastle code. AFAIK there's not a way to do that more directly using React. I moved all that code into the Bucket file specifically to have it all isolated into that single component.
@ggetz this PR has been cleaned up a bunch and should be good for another look
Looking good! Thanks @jjspace!