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.
Summary:
This is a proposal based loosely on the discussions I've had with @paulshen and @jwalke. It implements a shim for `React.DOM.input` (used as `<input>`) that supports two different use cases depending on whether `value` is provided or not.
If a `value` is //not// provided, the input will be initialized with the empty string (or `defaultValue`) and anytime the user changes the input, the `onChange` (or `onTextChange`) handler will be fired and the DOM will reflect the new changes.
React.renderComponent(
<input type="text" defaultValue="Untitled" onTextChange={handleChange} />,
container
);
If a `value` is provided, the input will be initialized to that value. Anytime the user changes the input, the `onChange` (or `onTextChange`) handler will be fired. However, the DOM will //not// reflect the new changes. If a `value` is provided, it is the responsibility of the owner to update the `value` prop passed in.
var value = "Untitled";
var input = React.renderComponent(
<input type="text" value={value} onTextChange={handleChange} />,
container
);
function handleChange(event) {
// Do something cool like strip out non-numbers.
var value = event.target.value.replace(/\D/g, '');
input.setProps({value: value});
}
This is just a start and we should build similar components for `textarea` and `select`. Also, this does not inject the new components because the changes are not backward compatible. Once we change all `<input>` uses to use `ReactDOMInput`, then we can inject.
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`.
When we move away from using the "id" attribute to identify
React-generated elements, we will need the cache (formerly
ReactDOMNodeCache) to be tied much more closely to the code that looks
elements up by ID (getDOMNodeID) and sets element IDs, since the magic of
document.getElementById will no longer be available.
The priming functions are going to come in handy when we create new DOM
fragments in mountComponent.
For backwards compatibility, the ReactDOMNodeCache and getDOMNodeID
modules still exist, but they are implemented entirely in terms of
functions exported from ReactID.
This adds a `toBeComponentOfType` method to `reactComponentExpect`. Now that we are injecting composite native components, `toBeDOMComponentWithTag` will not suffice and should be deprecated.
We have less dynamic arrays in the code base now so let's start warning for all
the cases where we pass dynamic arrays without keys.
I use the displayName to point out which component's render method was
responsible. I only warn once per component. If the child was created in a
different component (and passed as a property) I also show the owner of the
child. Maybe it should've attached the key at a higher level.
This does give false positives for arrays that are truly static. Those should
probably be refactored to use the XML syntax if possible.
06cff60bc1 made it so that `this.props.children` was no longer set when
none were provided.
var x = <div />;
This caused an issue if the code was relying on the following not
transferring children.
return this.transferPropsTo(<div />);
// this now transfer children
This fixes the last known parts of the flattening experiment. This has grown to
be somewhat complex and potentially fragile because of it. We may end up
reverting flattening in the future or address it slightly differently.
The purpose of this diff is to test if we've finally understood the real world
edge cases that flattening can lead to and how we have to key components to
cover those cases.
With this commit we never rekey the internal _key property. The semantics is
that once a component passes through a composite component, it's identity is
frozen.
props.key should accept numeric values and booleans which includes 0 and false.
This fixes the truthiness check.
We should never warn about missing key properties if a component is passed as a
static child. The _key acts as a flag to determine whether this component
was checked already.
Dumping the mock cache isn't dirying the modules in the open source version, so we have to unit test a different way. If we can fix the unit test framework, we should revert this.
Also, I added strict mode to `EventPluginRegistry.js`.
See: https://github.com/facebook/react/pull/91
Small utility that extracts and validates that there is only a single
child passed to a React composite component. The benefit here is that we
abstract away *how* the children are actually stored while we iterate on
different approaches. This way we won't break callsites as we try different
ideas. When we settle on a final approach, all of these callsites will still
work.
There are currently two places where we lookup and cache nodes: `ReactDOMNodeCache` and `ReactComponent`. Instead, we should just consolidate caches and make `ReactComponent` use `ReactDOMNodeCache`.
If you defined a global named `id` (a horrible name, I know) then
getDOMNodeID(window) would return that object. Since only DOM nodes can
have IDs, this should be a noop change otherwise.
Test Plan:
Verified that document.documentElement and document.body both support
getAttributeNode properly in latest Chrome and in IE8.
Dumping the mock cache isn't dirying the modules, so we have to unit test a different way. If we can fix our unit test framework, we should revert this.
Also, I added strict mode to `EventPluginRegistry.js`.
Summary: This invariant is unnecessary because `ReactComponent.Mixin.receiveProps` already asserts that this component is mounted. (Being mounted guarantees you have a DOM ID, look at `ReactComponent` and see when `this._rootNodeID` is mutated.)
This can be replicated with a custom component that always returns false`
from `shouldComponentUpdate`. A generic implementation might look like:
```
var StaticContainer = React.createClass({
shouldComponentUpdate: function() {
return false;
},
render: function() {
return this.transferPropsTo(this.props.children[0]);
}
});
```
And then used in JSX as
`<StaticContainer><div>Hello!</div></StaticContainer>`, resulting in
only `<div>Hello!</div>` being inserted into the DOM.
This fixes an edge case that can cause unnecessary mutations in the DOM. Namely, if a prop is falsey, it will get touched on every update by reconciliation. See unit test.
This cleans up the reconcilation path when adding a `style` prop (going from a falsey or no `style` to having one) by reducing the need for an object allocation and for-loop.
The `EventPluginHub` module was getting huge and scary. This pulls out all of the logic required to inject plugins and publish their event registration names into a new `EventPluginRegistry` module.
Functionally, nothing should have changed. I added many error checks to cover edge cases that we were not yet running into, but they are all in `EventPluginRegistry` and unit tested.
There is currently no way for components to know whether or not they are mounted. This means there's no way for callbacks to figure out if they can make certain assumptions (e.g. can `getDOMNode()` or `setState()` be safely invoked).
This adds an `isMounted` protected method that lets components properly handle callback behavior when unmounted.