This is the first step towards descriptors. This will start cloning the
component when it's mounted instead of mounting the first instance.
This avoids an issue where a reference to the first instance can hang around
in props. Since a mounted component gets mutated, the descriptor changes.
We don't need to clone the props object itself. Mutating the shallow props
object of a child that's passed into you is already flawed. Those cases need to
use cloneWithProps. A props object is considered shallow frozen after it leaves
the render it was created in.
We found that the component would break if we set any statics with the
value 0. It turns out @chenglou already ran into this with
d71736b3ed but the statics code was copied
earlier, and still has this falsy check. Made the same change, updated
the unittest.
grep -rl 'Copyright 2013 Facebook' static_upstream | xargs perl -pi -w -e s/Copyright 2013 Facebook/Copyright 2013-2014 Facebook/g;'
Not going to check in a script to do this since it will just change every year.
Closes#1006
This creates a membrane around the React component prototype. It warns if you
try to access properties on the component before it's unmounted. Before it's
mounted, it should be considered a descriptor and not an actual instance.
The workaround, for unknown types, is to access the constructor using
component.type which has static methods on it.
This codemods to shim any old-style JSX whitespace so that it renders the same as before.
Basically it sticks explicit `{' '}` spaces in where spaces are no longer implicit.
This reverts https://github.com/facebook/react/pull/576
This approach mutates the default props for the instance on each update,
which causes incorrect behavior. discussed with @balpert. can look into
cloning but this unbreaks.
This leaves statics as a way to define static methods and properties
that will be accessible on the return value of `React.createClass`
without changing the current spec.
This moves the static properties off of the root object and into
a 'statics' property. Then they are made available on the constructor so
they can be used directly and in mixins.
callbacks like shouldComponentUpdate, componentDidUpdate, etc. were getting the full, unsanitized context, instead of the one that's been filtered down to only the fields allowed to be visible by contextTypes.
Depends on #575; fixes#570. Now we'll be in trouble if someone tries to share objects between calls to getDefaultProps but that was already true of getInitialState and I haven't heard any complaints there.
This is the same number of allocations as before; we're just copying props in the other direction. (In any case, the copy happens only on mount and there are a couple dozen costlier things we're doing already at that time.)
Summary:
adds `this.context` which you can think of as implicit props, which are passed automatically down the //ownership// hierarchy.
Contexts should be used sparingly, since they essentially allow components to communicate with descendants (in the ownership sense, not parenthood sense), which is not usually a good idea. You probably would only use contexts in places where you'd normally use a global, but contexts allow you to override them for certain view subtrees which you can't do with globals.
The context starts out `null`:
var RootComponent = React.createClass({
render: function() {
// this.context === null
}
});
You should **never** mutate the context directly, just like props and state.
You can change the context of your children (the ones you own, not `this.props.children` or via other props) using the new `withContext` method on `React`:
var RootComponent = React.createClass({
render: function() {
// this.context === null
var children = React.withContext({foo: 'a', bar: 'b'}, () => (
// In ChildComponent#render, this.context === {foo: 'a', bar: 'b'}
<ChildComponent />
));
// this.context === null
}
});
Contexts are merged, so a component can override its owner's context **for its children**:
var ChildComponent = React.createClass({
render: function() {
// this.context === {foo: 'a', bar: 'b'} (for the caller above)
var children = React.withContext({foo: 'c'},() => (
// In GrandchildComponent#render,
// this.context === {foo: 'c', bar: 'b'}
<GrandchildComponent />
));
// this.context === {foo: 'a', bar: 'b'}
}
});
Currently, default props as defined by `getDefaultProps` are only used if a prop is not specified (using `X in Y` check).
However, this makes it difficult for composing components to pass along the state of not being defined, for example:
render: function() {
// If `this.props.someProp` is not set, `InnerThing` should use the default value.
return <InnerThing someProp={this.props.someProp} />;
}
This changes the requirement for falling back to the default value to an undefined check (using `typeof X === 'undefined'`).
Sometimes you may need to detect if a value is a valid React class constructor. This enables that and prevents future consumers from getting caught in the trap of depending on an internal implementation detail we might change.
Currently this works for classes created with `React.createClass` as well as `React.DOM.*`.
Today mixins can't easily be stateful because they can't provide getInitialState(). This allows multiple getInitialState() methods as long as they don't return objects that have conflicting keys. In that case, we throw.
There is a circular dependency between `ReactID`, `ReactMount` and
`ReactInstanceHandles`. Ben and I talked about this today. It seems like the
simplest solution is to consolidate a lot of the code that Ben recently wrote
into `ReactMount`. We can later find ways to trim code out of this module
without causing circular deps.
This prevents PhantomJS tests from hanging in the open-source React repo.
Until the advent of `"use strict"`, passing `null` as the context object
to `.call` or `.apply` resulted in `this` taking on the value of the
global object inside the invoked function.
Technically the `"use strict"` directive is supposed to make it possible
that `this === null`, but strict mode is not respected by all browsers,
including (unfortunately) PhantomJS.
Since these `expect`-ations are just testing binding behavior, let's not
make them also test strict mode `this` handling.
This behavior seemed incorrect for composite components.
- isComponentMounted() represents ReactComponent's lifecycle of mounting
- isMounted() represents ReactCompositeComponent's lifecycle of isMounted()
Therefore, ReactComponents no longer have isMounted(). I think this is fine since it was not supposed to be public anyway.
The original autobinding diff made some assumptions about how methods were called on components that had to be reverted. This diff
enforces those assumptions in a test
Per our discussion - this is the general approach we'd like to take for
the public facing API.
var MyComponent = React.createClass({
render: function() {
return <div onClick={this.myCallback} />;
},
myCallback: function() {
}
});
Also removed some unnecessary calls to `document.getElementById`, which
will eventually cease to work for React-specific IDs.
This clears the way for the deprecation of `ReactDOMNodeCache` and
`getDOMNodeID`.
If a React component's render() fatals, it may contaminate
ReactCurrentOwner. This will cause the owner to be set improperly for
the next React.renderComponent() invocation (which causes an owner to be
set when there shouldn't be one).
As it turns out, default values are very useful. This implements
getDefaultProps(), a hook for components to provide prop values when
a prop is not specified by the user.