-
Notifications
You must be signed in to change notification settings - Fork 264
Allow callback style setState #1
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
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -13,8 +13,20 @@ export class Container<State: {}> { | |
| this._listeners = []; | ||
| } | ||
|
|
||
| setState(state: $Shape<State>) { | ||
| this.state = Object.assign({}, this.state, state); | ||
| setState(state: $Shape<State> | (State => $Shape<State>)): void { | ||
| const prevState = this.state; | ||
| const newState = typeof state === 'function' ? state(prevState) : state; | ||
|
|
||
| /** | ||
| * allow either early return or ternary return of previous state to | ||
| * propagate correctly through component tree by not calling _listeners | ||
| * and leaving old state in place. | ||
| */ | ||
| if (newState == null || newState === prevState) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think returning early if a shallow comparison fails would be a breaking change, and incompatible with React's
An example demonstrating a successful state-mutation update is here. My second concern is that React emits its own development-time console warnings for passing For both of those reasons, I think it might be best to eliminate the conditional early return altogether, and let React do its thing. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So in other words, I would think about rolling back ff77c96.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I think this is not true with react@16. I don't use this feature but returning What we might need to introduce here is 2 distinct paths for objects & function styles. Because of the setState(state: $Shape<State> | (State => $Shape<State>)): void {
const prevState = this.state;
let newState
if (typeof state === 'function') {
newState = state(prevState)
if (newState === null) {
return;
}
} else {
newState = state
if (process.env.NODE_ENV !== 'production' && newState === null) {
console.warn('write a nice dev warning here')
}
}
if (newState === prevState) {
return
}
this.state = Object.assign({}, prevState, newState);
this._listeners.forEach(fn => fn());
}Does it make sense to u?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah I understand how to get there code-wise, I'd just like to have @jamiebuilds's input on what the desired behavior is.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well, the API should mirror React's API as closely as it can. So I'd say we should just follow that path.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah since this is already only conceptually similar to setState, I'm not convinced we should be following React to the letter vs doing the principally right thing. Their API tradeoffs aren't necessarily the same as those of a pure state manager. I'll update tomorrow, and hopefully get some time in to write those tests.
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I want it to match the React behaviour as closely as possible. Refactoring component state into container state should be near seamless There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wow my mistake! I was operating under the impression the @StevenLangbroek Given the above discussion I concede it makes sense to have custom error reporting and perhaps disregard what React does or does not report as a mistake. However, the documentation for Unstated is currently written without any specification for
If there's an intent to change that, it should be documented well, and also be considered a breaking change which would merit a new major version. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @jamiebuilds I missed your reply, but I guess I should have just let your comment sit. 😄 I appreciate that sentiment - it's my favorite thing about this library. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Hi @StevenLangbroek , can we make one constant file and manage this kind of string |
||
| this.state = prevState; | ||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this even necessary? Or should I just return?
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. assignment indicates that it changes something, I think |
||
| return; | ||
| } | ||
| this.state = Object.assign({}, prevState, newState); | ||
| this._listeners.forEach(fn => fn()); | ||
| } | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.
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.
instead of "function", can we make it in a constant file and export it @StevenLangbroek