Just a bit of byte savings for server rendering. Props to @benjamn for the base36 idea (and for making this diff easy).
With a little work we could probably get rid of the .r as well.
This changes React to throw when `ReactID.getNode()` fails to find a node. This method is used by two call sites:
- Implements `ReactComponent#getDOMNode`. This method already throws if a component is not mounted, and //all mounted components should be able to find their rendered root nodes//.
- Used by `ReactDOMIDOperations`. These call sites aleady assume that `getNode` returns a non-null. Currently, if the node is not found, this is the site that fatals (and the stack trace is much harder to debug).
The error message should make it //a lot// easier to debug unexpected DOM trees. In particular, this will help track down all the places where the browser inserts `<tbody>` unexpectedly.
This fixes a bug with components constructed with no owners, for example:
// Both the <div> and <span> have no owners.
React.renderComponent(<div><span /></div>, node);
They should have a composition level of 1 and their keys should be prefixed with 0 to indicate they were created without owners. However, they currently incorrectly get a composition level of 0 (which means that //their// children will have keys prefixed with 0, which is wrong).
The current `ReactInstanceHandles` has a bug where `findComponentRoot` barfs if it comes across a node that was not identified by React (via `ReactID`). This fixes that.
This was always a bug, but it became more apparent once we switched to `data-reactid` because arbitrary `document.createElement`'d nodes are much more likely to have an `id` than they are to have a `data-reactid`.
This final change is what we've all been waiting for.
Note that it no longer makes sense to use `document.getElementById` in
`getNode`, because that only ever worked with "id" attributes.
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.
The `getDefaultProps` return value should not be dependent on any external data (including `this.props` and `this.state`), so the return value should be consistent everytime we call it.
This caches the return value so we do not do work and allocate memory unnecessarily.
A node is considered valid if it
1. has the expected ID (more of a sanity check than something that is
ever likely to go wrong), and
2. is contained by a currently mounted container.
When these requirements are met, we can be confident that
`ReactMount.findReactRenderedDOMNodeSlow(node.id) === node`, which is
important for cache consistency because `findReactRenderedDOMNodeSlow` is
what we fall back to when we don't find a node in the cache.
Point 2 is a subtle requirement, because it allows nodes to be valid even
if they are not currently contained by a document. Rendering into a
detached node is okay, in other words (which is something that
`document.getElementById` never properly accounted for).
Containment testing takes linear time in the depth of the DOM, which
sounds unfortunate until you realize that virtually all browsers support a
native `ancestor.contains(descendant)` method, and in practice the vast
majority of nodes are either orphaned with `.parentNode === null` or not
very deep relative to their container.
Upgrade `TextChangeEventPlugin` to be the `onChange` event that React
fires. In React, `onChange` will now fire when `input` fires for form elements in
modern browsers.
Handle this for:
input[type=text]
input[type=password]
input[type=checkbox]
input[type=radio]
textarea
select
Support:
- OSX Chrome
- OSX Safari
- OSX Firefox
- Win 7 / IE8
- Win 7 / IE9
- Win 7 / IE10
Everything works but caret selection / placement differs from browser to
browser.
For <select> elements, the event is fired with `change`. This is a
conscious decision, even though in some browsers (OSX firefox, IE), it
can be argued that the event should fire more due to how the UI looks.
Builds on https://github.com/facebook/react/pull/75, which handled only
text inputs.
These modules have been superseded by `ReactID`. Since they were only used
internally, and I have updated all client code that previously assumed
their existence, I believe they can be dropped for good.
Although it would have been nice to prime the entire tree and achieve a
cache hit rate of 100%, that cost would have to be paid up front, during
page rendering.
This patch avoids priming up front in favor of making the most of the work
done by `ReactMount.findReactRenderedDOMNodeSlow`, which calls
`ReactID.getID` while traversing the rendered DOM. The insight is this: if
`getID` simply primes the cache whenever it finds a new ID, then
`findReactRenderedDOMNodeSlow` will end up priming quite a few more nodes
that are actually involved in `ReactID.getNode` lookups, and we won't need
`primeTree` at all.
`.grunt/` is the directory that is suggested for storing task related
files, and this file is not useful if it gets wiped out often. So I'm
moving the compare_size cache into `.grunt/` so we keep it around
longer.
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() {
}
});