-
Notifications
You must be signed in to change notification settings - Fork 47.4k
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
[Fiber] Complete ES6 Class related errors support #8156
Changes from all commits
306518c
071b884
9618961
184a82a
4a87efd
edb58c2
3c3f44b
a69001c
102ece5
2b0fc93
89377af
6a92c3f
f8289a7
9ae84f1
c8dc3c9
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 |
---|---|---|
|
@@ -24,6 +24,11 @@ var { | |
var { isMounted } = require('ReactFiberTreeReflection'); | ||
var ReactInstanceMap = require('ReactInstanceMap'); | ||
var shallowEqual = require('shallowEqual'); | ||
var warning = require('warning'); | ||
var invariant = require('invariant'); | ||
|
||
|
||
const isArray = Array.isArray; | ||
|
||
module.exports = function(scheduleUpdate : (fiber: Fiber) => void) { | ||
|
||
|
@@ -91,6 +96,98 @@ module.exports = function(scheduleUpdate : (fiber: Fiber) => void) { | |
return true; | ||
} | ||
|
||
function getName(workInProgress: Fiber, inst: any): string { | ||
const type = workInProgress.type; | ||
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. Can we please not calculate these fields in production if we're not planning to print anything? It's fine to extract this to 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. You're right, I'm going to change that |
||
const constructor = inst && inst.constructor; | ||
return ( | ||
type.displayName || (constructor && constructor.displayName) || | ||
type.name || (constructor && constructor.name) || | ||
'A Component' | ||
); | ||
} | ||
|
||
function checkClassInstance(workInProgress: Fiber, inst: any) { | ||
if (__DEV__) { | ||
const name = getName(workInProgress, inst); | ||
const renderPresent = inst.render; | ||
warning( | ||
renderPresent, | ||
'%s(...): No `render` method found on the returned component ' + | ||
'instance: you may have forgotten to define `render`.', | ||
name | ||
); | ||
const noGetInitialStateOnES6 = ( | ||
!inst.getInitialState || | ||
inst.getInitialState.isReactClassApproved | ||
); | ||
warning( | ||
noGetInitialStateOnES6, | ||
'getInitialState was defined on %s, a plain JavaScript class. ' + | ||
'This is only supported for classes created using React.createClass. ' + | ||
'Did you mean to define a state property instead?', | ||
name | ||
); | ||
const noGetDefaultPropsOnES6 = ( | ||
!inst.getDefaultProps || | ||
inst.getDefaultProps.isReactClassApproved | ||
); | ||
warning( | ||
noGetDefaultPropsOnES6, | ||
'getDefaultProps was defined on %s, a plain JavaScript class. ' + | ||
'This is only supported for classes created using React.createClass. ' + | ||
'Use a static property to define defaultProps instead.', | ||
name | ||
); | ||
const noInstancePropTypes = !inst.propTypes; | ||
warning( | ||
noInstancePropTypes, | ||
'propTypes was defined as an instance property on %s. Use a static ' + | ||
'property to define propTypes instead.', | ||
name, | ||
); | ||
const noInstanceContextTypes = !inst.contextTypes; | ||
warning( | ||
noInstanceContextTypes, | ||
'contextTypes was defined as an instance property on %s. Use a static ' + | ||
'property to define contextTypes instead.', | ||
name, | ||
); | ||
const noComponentShouldUpdate = typeof inst.componentShouldUpdate !== 'function'; | ||
warning( | ||
noComponentShouldUpdate, | ||
'%s has a method called ' + | ||
'componentShouldUpdate(). Did you mean shouldComponentUpdate()? ' + | ||
'The name is phrased as a question because the function is ' + | ||
'expected to return a value.', | ||
name | ||
); | ||
const noComponentDidUnmount = typeof inst.componentDidUnmount !== 'function'; | ||
warning( | ||
noComponentDidUnmount, | ||
'%s has a method called ' + | ||
'componentDidUnmount(). But there is no such lifecycle method. ' + | ||
'Did you mean componentWillUnmount()?', | ||
name | ||
); | ||
const noComponentWillRecieveProps = typeof inst.componentWillRecieveProps !== 'function'; | ||
warning( | ||
noComponentWillRecieveProps, | ||
'%s has a method called ' + | ||
'componentWillRecieveProps(). Did you mean componentWillReceiveProps()?', | ||
name | ||
); | ||
} | ||
|
||
const instanceState = inst.state; | ||
if (instanceState && (typeof instanceState !== 'object' || isArray(instanceState))) { | ||
invariant( | ||
false, | ||
'%s.state: must be set to an object or null', | ||
getName(workInProgress, inst) | ||
); | ||
} | ||
} | ||
|
||
function adoptClassInstance(workInProgress : Fiber, instance : any) : void { | ||
instance.updater = updater; | ||
workInProgress.stateNode = instance; | ||
|
@@ -102,6 +199,7 @@ module.exports = function(scheduleUpdate : (fiber: Fiber) => void) { | |
const ctor = workInProgress.type; | ||
const props = workInProgress.pendingProps; | ||
const instance = new ctor(props); | ||
checkClassInstance(workInProgress, instance); | ||
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. Can we avoid checking if we are resuming work and recreating the instance? Check should only be done once. 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. Now, That's the interesting part! I'll try to do that... 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. It wasn't that hard ... Maybe there is a more elegant way to do that though ... 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. Actually, this is not sufficient since the state may depend on class Foo extends React.Component {
state = this.props.bar ? {} : [];
} I'd rather check it every time. For warnings, we should probably ideally dedupe though. |
||
adoptClassInstance(workInProgress, instance); | ||
return instance; | ||
} | ||
|
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 have a module that lets you do this now.
getComponentName
.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 guess that module doesn't use
inst.constructor
as a fallback. Hm. Maybe it should? Don't know. I'll land this for now while we figure that out.