-
Notifications
You must be signed in to change notification settings - Fork 47k
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
Trigger a proper no-op warning for async state changes on server #7127
Conversation
}, this) | ||
.reduce(function(ReactUpdate, funcObj) { | ||
return Object.assign(ReactUpdate, funcObj); | ||
}); |
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.
Not sure about this though, maybe there is a way to do better there. I personally would have used Immutable for this kind of trick, but, I understand the constraints here. So if I can do that differently, just tell me!
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.
Can you please unwind this to be simple (repetitive) code instead? IMO meta programming is not worth it here :-)
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.
Do I understand correctly that the intention is to use ReactUpdateQueue during mounting so initial setState works but switch it out right after the mounting is over?
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.
We would also need a test for forceUpdate
.
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.
I can do that, especially if I can consider that UpdateQueues will be identical. Yes, you understood that correctly, should I change my comment to be more clear maybe ?
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.
It will be more obvious after the unwinding.
@@ -7,6 +7,7 @@ | |||
* of patent rights can be found in the PATENTS file in the same directory. | |||
* | |||
* @providesModule ReactReconcileTransaction | |||
* @flow weak |
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.
Oh! maybe you don't want those! Can delete them if you ask, but flow helped me though (once again!)...
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.
Would it be possible to add any type annotations if you're already using flow? I know there have been some recent efforts by @vjeux to add annotations. I don't see any files that are using weak mode either so that might be something to consider.
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.
I can totally do that! I wasn't sure about babel on the React codebase but as @gaearon pointed out, babel is there so, yes I can do it. (After this, I can also start to add some flow throughout the codebase if you are ok with that, you can even point me to critical parts. However, the flow declarations for react already are super complete, so I'm not sure there is really critical parts).
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.
I have no idea what flow weak does, can you educate me? Also what isn't working with normal flow?
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 is 53 flow errors in ReactCompositeComponent
(missing annotations), I'll do this file in a separate PR.
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.
weak allows unannotated function defs, it is often used for progressive addition of flow, that way you can start typechecking but in the absence of annotation, flow will consider the params automatically as any
. https://flowtype.org/docs/existing.html#weak-mode
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.
For instance, I think you could add @flow weak
everywhere in this codebase without raising much issues. The upside would be that flow could still emit warnings on very risky things it managed to infer.
Still working on it, don't trust the bot ! I will rebase/squash at the end don't worry ! |
@gaearon: took your comments into consideration and rebased/squashed the changes. |
// We use a ReactNoopUpdateQueue that switches to ReactUpdateQueue while | ||
// mounting | ||
var transaction = this; | ||
return { |
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 allocates an object any time getUpdateQueue
is called. Instead, it should only be initialized once. For example, you could write a class called ReactServerUpdateQueue
that would take transaction
as a constructor argument.
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.
Yes, good catch! I will refactor that!
'Warning: setState(...): Can only update a mounted or mounting' + | ||
' component. This usually means you called setState() on an' + | ||
' unmounted component. This is a no-op. Please check the code for' + | ||
' the Component component.' |
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.
I would actually change the message to something more adapted to the server:
Warning: setState(...): Can only update a mounting component. This usually means you called setState() on an unmounted component or already mounted component on a server. This is a no-op. Please check the code for the Component component.
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.
I agree (if it’s not super difficult). Note that server has no concept of “already mounted component”. I would say “This usually means you called setState() outside componentWillMount() on the server.” or something like this.
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.
I'll think of something. I really like react warnings because they are super-clear, I want to continue in this direction here...
Finishing with this and squashing/rebasing then |
Again, don't trust the bot, still needs revision! |
Thanks! |
No problem, I was going to do a second PR for that afterwards but I can do that just now! |
Ok, I will need some time to do that ... I need to go deep sometimes... |
Ok so I'll just remove some annotations here so we can merge it. Still, I'll stash my work to continue that afterwards! |
@gaearon so I only left the flow typecheck in |
@@ -30,10 +31,11 @@ var noopCallbackQueue = { | |||
* @class ReactServerRenderingTransaction | |||
* @param {boolean} renderToStaticMarkup | |||
*/ | |||
function ReactServerRenderingTransaction(renderToStaticMarkup) { | |||
function ReactServerRenderingTransaction(renderToStaticMarkup: boolean) { |
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.
Nit: : boolean
is now unnecessary here.
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.
yep
This commit fixes #5473: ReactDOMServer.renderToString: presence of onClick handler causes errors on async update This commit performs the following changes: - Adds a getUpdateQueue method to ReactServerRenderingTransaction, ReactReconcileTransaction, ReactNativeReconcileTransaction and ReactTestReconcileTransaction - Make the ReactCompositeComponent call this getUpdateQueue instead of using ReactUpdateQueue that was unwanted at certain moments on server - On ReactServerRenderingTransaction, dispatch ReactUpdateQueue's methods while rendering and warning methods afterwards. This is done through the new ReactServerUpdateQueue class - Added a series of tests that mimics the case presented in #5473 with setState, forceUpdate and replaceState - Add flow typechecking on concerned files
Thanks! |
It was added in #7127 but this file isn’t type checked anyway.
Thank you for reviewing me. That was a good and instructive experience! |
This commit fixes #5473: ReactDOMServer.renderToString: presence of onClick handler causes errors on async update This commit performs the following changes: - Adds a getUpdateQueue method to ReactServerRenderingTransaction, ReactReconcileTransaction, ReactNativeReconcileTransaction and ReactTestReconcileTransaction - Make the ReactCompositeComponent call this getUpdateQueue instead of using ReactUpdateQueue that was unwanted at certain moments on server - On ReactServerRenderingTransaction, dispatch ReactUpdateQueue's methods while rendering and warning methods afterwards. This is done through the new ReactServerUpdateQueue class - Added a series of tests that mimics the case presented in #5473 with setState, forceUpdate and replaceState - Add flow typechecking on concerned files (cherry picked from commit dbdddf1)
…ebook#7127) This commit fixes facebook#5473: ReactDOMServer.renderToString: presence of onClick handler causes errors on async update This commit performs the following changes: - Adds a getUpdateQueue method to ReactServerRenderingTransaction, ReactReconcileTransaction, ReactNativeReconcileTransaction and ReactTestReconcileTransaction - Make the ReactCompositeComponent call this getUpdateQueue instead of using ReactUpdateQueue that was unwanted at certain moments on server - On ReactServerRenderingTransaction, dispatch ReactUpdateQueue's methods while rendering and warning methods afterwards. This is done through the new ReactServerUpdateQueue class - Added a series of tests that mimics the case presented in facebook#5473 with setState, forceUpdate and replaceState - Add flow typechecking on concerned files
It was added in facebook#7127 but this file isn’t type checked anyway.
Looks like this was actually a breaking change. It broke some previously working setState calls. |
Can you file an issue and provide code reproducing it? setState calls while rendering is in progress should still work. After mounting is over they should become no-ops instead of throwing like before. What kind of calls are breaking? |
This commit fixes #5473: ReactDOMServer.renderToString: presence of onClick
handler causes errors on async update
This commit performs the following changes:
ReactReconcileTransaction, ReactNativeReconcileTransaction and
ReactTestReconcileTransaction
ReactUpdateQueue that was unwanted at certain moments on server
while rendering and ReactNoopUpdateQueue's methods afterwards
replaceState