-
Notifications
You must be signed in to change notification settings - Fork 59
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 forceUpdate method to Component #271
Conversation
@@ -276,6 +282,16 @@ class Component extends EventEmitter { | |||
} | |||
|
|||
/** | |||
* Forces a an update that ignores `shouldUpdate` for components whose | |||
* render depends on external variables. |
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.
Possible typo a an update
?. Also, maybe unnecessary space in the second line?
* Forces a an update that ignores `shouldUpdate` for components whose | ||
* render depends on external variables. | ||
*/ | ||
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.
As per React, forceUpdate takes a callback... probably because it works asynchronously... should we take one as well? Do we have usage examples of 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.
It won't hurt to add the functionality, though technically someone could achieve this by listening to the next rendered
event.
component.once('rendered', function() {
console.log('just force updated');
});
component.forceUpdate();
Though I think we should add the callback even if it's just for cleanliness.
component.forceUpdate(function() {
console.log('just force updated');
});
@@ -85,6 +85,12 @@ class Component extends EventEmitter { | |||
this.eventsStateKeyHandler_ = null; | |||
|
|||
/** | |||
* Whether the element is currently force updating. |
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 we explain what to be force updating
means a bit more? Not sure if it is common knowledge, but maybe something along the lines, wether it should ignore
shouldUpdate and always render...
, something that doesn't include the variable name :)
@@ -400,6 +417,14 @@ class Component extends EventEmitter { | |||
} | |||
|
|||
/** | |||
* Returns true if component is currently force updating. |
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.
Similar to the other comments about this :)
776160d
to
83ce193
Compare
@jbalsas, updated. |
What's the goal of this |
From React.Component#forceUpdate:
This can pretty much always be bypassed by a proper state/prop modification, but here's a simple dummy example using class App extends React.Component{
constructor(){
super();
this.forceUpdateHandler = this.forceUpdateHandler.bind(this);
};
forceUpdateHandler(){
this.forceUpdate();
};
render(){
return(
<div>
<button onClick= {this.forceUpdateHandler} >FORCE UPDATE</button>
<h4>Random Number : { Math.random() }</h4>
</div>
);
}
} |
I see, that's cool. |
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.
Hey @Robert-Frampton, this looks good in general, I have only one concern about how the forceUpdating
flag is being managed which might be too convoluted since I haven't even been able to put it into a failing test 😂
it('should clean the isForceUpdating if render fails for some reason', function() {
var CustomComponent = createCustomComponentClass((component) => {
// Something can happen that prevents a successful render?
// throw new Error('cant render');
});
comp = new CustomComponent();
var listener = sinon.stub();
comp.forceUpdate(listener);
assert.equal(listener.callCount, 0);
assert.isFalse(comp.isForceUpdating());
});
it('should not call the forceUpdateCallback if render fails for some reason', function() {
var failRender = true;
var CustomComponent = createCustomComponentClass((component) => {
if (failRender) {
// Something can happen that prevents a successful render?
// throw new Error('cant render');
failRender = false;
} else {
component.informRendered();
}
});
comp = new CustomComponent();
var listener = sinon.stub();
comp.forceUpdate(listener);
assert.equal(listener.callCount, 0);
assert.isFalse(comp.isForceUpdating());
comp.render();
assert.equal(listener.callCount, 0);
assert.isFalse(comp.isForceUpdating());
});
My concern is that something may happen during a render phase that prevents us from cleaning up, and then we'll carry that information to a subsequent render...
Do you think that's possible and/or preventable?
Hey @jbalsas This is actually slightly related to what I was hoping to implement for #281. Right now it's pretty hard to catch errors that originate from incremental dom. For example, if you put something like this in your template... {template .render}
<div></span>
{/template} And try to catch the error by doing... forceUpdate(opt_callback) {
this.forceUpdateCallback_ = opt_callback;
this.forceUpdating_ = true;
try {
this.updateRenderer_();
} catch (e) {
this.forceUpdateCallback_ = null;
this.forceUpdating_ = false;
}
} It won't actually catch it, the error just bleeds through due to how we are invoking incremental dom. I think we can accomplish better error handling, but I think it's outside the scope of this branch. I'm fine with holding off on these changes until we improve error handling if you'd like. |
Hey @Robert-Frampton, that's fine, I was thinking more along the lines of forceUpdate(opt_callback) {
this.updateRenderer_({
forceUpdate: true,
updateCallback: opt_callback
});
} If there's a way to push that down the line, we won't hold state in the components and avoid these type of issues. It should also be easiest to test since there are no side-effects or additional coupling between renderer and component. Not sure if it's doable, though 🤷♂️ |
Oh I see, yeah I can look into it. |
83ce193
to
23696f2
Compare
Hey @jbalsas I was able to remove the On a somewhat unrelated note, I noticed that the |
Merged! |
No description provided.