-
Notifications
You must be signed in to change notification settings - Fork 4.2k
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
Serializer: Fix Invariant error related to hooks #15873
Conversation
} from 'lodash'; | ||
import { __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED } from 'react'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
😅
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
moderator note there was some spam commenting on this issue. I reported the user to github and blocked them from this repo
useEffect: noop, | ||
useDebugValue: noop, | ||
}; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was mostly just to get the ball rolling on one option which is monkey patching the ReactCurrentDispatcher
before doing the render. However, if we go this route, we'll probably have to reproduce similar logic for hooks found here. This seems fragile and increases maintenance burden. The other (maybe not significant) potential issue is that essentially any logic in a useEffect
or useLayoutEffect
hook in a rendered component will not fire if we use something similar to ReactPartialRendererHooks
because this serializer is effectively doing similar to what server type tasks do (as opposed to browser).
If renderToString
is mostly used for the save
function of blocks (stateless components) I wonder if we should simply detect usages of withSelect
/hooks and simply NOT support them (throw errors?).
This is a great article to read that provides insight to the api around the renderers: https://overreacted.io/how-does-setstate-know-what-to-do/ Essentially GB's custom renderer will have to implement it's own dispatcher to support hooks (assuming it's desired that hooks are supported) |
There are two things which prevent it from being more obviously-problematic:
|
I think I've just encountered this issue too. I want to have access to the current post in the save function as I want to use the current url for a share functionality. Here is the code which produces the error:
|
I've just bumped into the same issue. In my case, the reason was Webpack bundling second, different version of React (16.4) from the one globally available through Gutenberg (16.8), just like here: facebook/react#15270. Externalizing React and ReactDOM did the trick for me. |
@pascalknecht from the docs around the save function:
In other words, it shouldn't depend on external sources outside of the attributes for your block. This is one of the reasons why this isn't a high priority issue right now. What you might want to consider doing is make whatever value you are constructing as a |
@WunderBart Thanks for reporting your findings in here but on the surface it does not sound like you were experiencing the same issue. The error being reported in this issue has nothing to do with specific React version - so I'm guessing you encountered another invariant error (potentially related to hooks) and thought these were the same issues. Glad you found a solution for your issue though 😄 |
Hi folks, I've been running into this one a lot over the past week as I didn't want to bake some theme level settings into an attribute for every block. As a workaround, I'm using a shim of the import { useSelect as baseUseSelect } from '@wordpress/data';
export function useSelect( mapper ) {
try {
// Use builtin selector.
return baseUseSelect( mapper );
} catch ( e ) {
// Re-throw if exception type is not expected.
if ( 'Invariant Violation' !== e.name ) {
throw e;
}
// Pass global data object to mapper. (No props + side effects?)
return mapper( wp.data.select );
}
} This is ugly and I have no idea what sort of side effects this has - but it seems to be working in my current project where that part of the state isn't changed between editor load and save. Note that the // ...
save( { attributes } ) {
// Using shim function. (2nd arg defaults to this scope's save() props.)
const { availableBreakpoints } = useSelect( ( select, props = arguments[0] ) => {
return {
availableBreakpoints: select( 'example/grid' ).getBreakpoints()
}
} );
console.log(availableBreakpoints)
// etc...
}, I have a feeling this is a terrible idea, so please don't rely on this! |
@nerrad Per @kauhat's comment, do you think it might be realistic to consider this as an allowable error using a simple I haven't dug into it too much, but I see that errors in React are coded, so it might be something we could reliably identify: I guess, per your original comment, it depends if we need the hooks to run. Did your original approach here solve that problem? |
The original approach basically used a custom dispatcher that replaced existing hooks with noop. So effectively it prevents the errors. A try/catch could do something similar I suppose. I'd be wary about referencing the original hook as that risks introducing side-effects into |
Oh, I was thinking that the |
I was thinking the same too, what were you thinking the catch would do, just silently discard the error and allow things to continue? |
Pretty much this, yes. As long as we're able to reliably limit it to this very specific error, and throw all other errors as normal. |
Now that |
Closing this out due to inactivity and in order to keep current PRs more relevant. Welcome folks to open a new PR to address this issue as it arises going forward and am happy to reopen this if that's preferred! |
Description
This is an error that currently doesn't seem to be surfacing anywhere in the interface for users but was spotted by @aduth when testing #13879 against the work merged in from #15737 (introducing
useSelect
and implemented in `withSelect).For his tests he was doing something like this in the console:
This produced the error:
This was troubleshot for a few minutes in slack and taking cues from some of the things uncovered there I spent some time trying out a few things and ended up with this rough pull which allows for
renderToString
to run without errors for the above code snippet (producing the expected<div>Howdy There</div>
output). However, I don't think this is the solution we'll roll with (won't we need hooks to actually run?). I decided to throw this pull up anyways and it can be iterated on with ideas for solving.Note:
Dispatcher
but that resulted in recursion errors (try it and you'll see). Actual error isUncaught RangeError: Maximum call stack size exceeded