-
-
Notifications
You must be signed in to change notification settings - Fork 635
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
add $F as a force property to the component instance #1535
Conversation
@@ -131,11 +136,12 @@ export class Component<P = {}, S = {}> implements IComponent<P, S> { | |||
public $LI: any = null; // LAST INPUT | |||
public $UN: boolean = false; // UNMOUNTED | |||
public $CX: any = null; // CHILDCONTEXT | |||
public $QU: Function[] | null = null; // QUEUE | |||
public $QU: Function[] | null = null; // QUEUE |
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.
Why is this change needed?
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.
No need, reverted it
@@ -74,7 +77,9 @@ export function rerender() { | |||
|
|||
while ((component = QUEUE.shift())) { | |||
if (!component.$UN) { | |||
applyState(component, false); | |||
const force = component.$F; | |||
component.$F = false; |
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.
Why is this line needed?
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.
As $F
stores the information whether changes should be forced or not, we assume that they are not forced by default unless forceUpdate
is called. The default value of $F
is false.
If forceUpdate
is called we switch $F
to true, and wait before it will be time for our component to render. After the component updates, we want to return the default value for the component. So, it's why I'm using $F = false
.
And finally, the component potentially could plan further changes via setState
or even forceUpdate
during its updating cycle. It means we want to set up all defaults before the component starts its updating cycle. So I cache value in const force
.
I think there is larger issue here. So what should happen if there are 2 setState calls in queue, then one forceUpdate call is made. now after this change SCU will not be called for those 2 setStates in the queue, is this expected behavior? |
@Havunen At the moment if we have 2 (or more) pending setState the pending state changes will be merged here: https://github.com/infernojs/inferno/blob/master/packages/inferno/src/core/component.ts#L26-L28 Talking about |
Yes however there has been many bugs reported in the past that some callback (SCU, didUpdate or similar) is not called in some particular case and their application does not work same way as it does with react. I have seen people write code where they call setState X times and they are expecting same number of calls to component (did/will) update so this change is breaking change for those applications if they use forceUpdate.. :/ |
I think to merge this we would at minimum need to add test cases for these cases and have the expected result so that its compatible with React implementation |
Yes, it seems like a breaking change, as when a developer calls Also, If I'm not mistaken about the difference between Inferno and React, that react doesn't merge all pending states to 1 update (e.g. React merge them if they are called inside react event handler or lifecycle method, but doesn't merge if the changes are planned in the setTimeout). Inferno plans all changes as a part of the QUEUE and merges them if the component is presented in the QUEUE. I'll add a test case |
React behavior is not consistent in all cases, it depends how setState is called. If its called from event handlers it works diferently... Calling setState from event handlers ( type into the text input and check console log ) When setstate call origin is not event handler it does it different way see ( open url and check console log ): |
As I said, and you example is also about it: React merges changes if they are called inside react event handler or lifecycle method. BTW your examples work in the same way during the update, but in the first external call yes, the second example has different behavior, I agree Your first example: only 1 render during updating cycle which was called because of event handler: Your second example: 3 re-renders during init, as each setTimeout and forceUpdate makes different component update. However, during updating cycle we have only 1 re-render: My example with timeouts: https://jsfiddle.net/egd1kuz6/ However, Inferno already has a different flow: it updates only 1 time per component as all the updates are stored in the QUEUE and we check if there are any of the components in the QUEUE. So, I think it's consistent behavior and my changes only support it. |
Ok, thanks for tests LGTM :) |
Thanks for merging @Havunen ! |
Objective
This PR adds
$F
instance field which is in charge of the force updating component. It makesforceUpdate
work predictableCloses Issue
It closes Issue #1534