Currently we use an invariant to prevent this code pattern. That is really
aggressive for something that doesn't actually put React in a bad state. This
diff replaces invariants with warnings and makes those code paths no-ops.
Eslint now allows us to use a different parser, which allows us to use
esprima-fb explicitly. This means we don't have to wait for espree to add
things like rest-param parsing. Though we do need eslint to upgrade its rules
to handle that AST.
I had hoped to enable parsing of our tests but we can't do that until we
change esprima-fb's XJS nodes to JSX.
While I was here, I also enabled the no-unused-vars rule since eslint
understands template strings. I also made the single quote enforcement
actually fail instead of just warn.
This triggers a warning if you try to pass a keyed object as a child.
You now have to wrap it in React.addons.createFragment(object) which
creates a proxy (in dev) which warns if it is accessed. The purpose of
this is to make these into opaque objects so that nobody relies on its
data structure.
After that we can turn it into a different data structure such as a
ReactFragment node or an iterable of flattened ReactElements.
We've actually diverged more with some modules, but we don't want
a cascade of dependencies out here. Mostly, the changes internally that
we don't want are tied to FB infrastructure but otherwise are
functionally equivalent (usually around error reporting, code monitoring).
This diff enables setState to accept a function in addition to a state partial. If you provide a function, it will be called with the up-to-date `state, props, context` as arguments.
This enables some nicer syntax for complex setState patterns:
If setState is doing an increment and wants to guarantee atomicy, you need a function:
```
this.setState(state => ({ number: state.number + 1 }));
```
This atomicy is particularly important if setState is called multiple times in a single frame of execution as the result of complex user actions. It's a tricky bug to chase down and difficult to determine how to fix when you find it. The current pattern of reaching into _pendingState relies on an implementation detail.
In this example: props.doAction() may result in your ancestor re-rendering and providing you with new props. If setState is called directly with an object literal referencing `this.props`, it will use the *old* version of props, not the new value. Using a function solves for this case:
```
this.props.doAction();
this.setState((state, props) => ({ number: state.number * props.multiplier }));
```
enqueueCallbackInternal forgot to schedule an update.
We could rely on the implicit contract of enqueueElement to do it. However,
if we're currently outside a transaction, it'll flush synchronously. Before
we enqueue the callback. We could also enqueueCallback before we
enqueueElement, but that causes a fragile relationship between them. E.g.
enqueueElement should not need to schedule an update if it is the same
element.
In 1.4.0 we can use the TypeScript API directly to preprocess our files.
This lets us get rid of a dependency.
https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API
We can also use this to provide our default libraries so that we don't
need to keep the references in the test file.
It's possible to configure Jest to not dump the module cache between
specs. This makes it tricky when we silence warnings one a 2nd call.
In this case, the same message was getting logged so when we expected
the count of warning calls to increment, it didn't.
This makes it more difficult to find bugs in mixins both dynamically
and using a static type system.
We also don't have a way to find these to be upgraded to a new mixin
syntax if we needed to.
This hook is currently an optional noop but could be made required to
create a mixin class.
We freed up this internal name by removing the internal base class.
We're now free to use this name as it was intended.
ReactDOMComponent and ReactCompositeComponent are still confusing as
they're internal but we'll rename them later.