Dealing with immutable data is hard. This provides a simple helper (ported from the IG codebase) that makes dealing with immutable JSON data easier. Designed to be familiar for people who use MongoDB.
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
The key idea here is that you're always rendering `this.state.children`, not
`this.props.children`. When combined with `cloneWithProps()` this means we can
keep them in the DOM as long as we want. We add new children and reactively
update existing ones using `setState()` inside of `componentWillReceiveProps()`
so `this.state.children` always has the latest versions of components. Since we
may be keeping old components around that are no longer in
`this.props.children` we need a way to figure out where they should be inside
of the combined `this.state.children` list. `ReactTransitionChildMapping` does
this for us.
Based on that infrastructure we can build the interface we always wanted: enter
and leave lifecycle hooks.
When a component is added to the DOM, `componentWillEnter(callback)` gets
called. Call the callback when you're done animating and `componentDidEnter()`
will be called.
When a component is about to be removed from the DOM,
`componentWillLeave(callback)` gets called. Call the callback when you're done
animating and `componentDidLeave()` will be called and the component will
*actually* be removed from the DOM. It won't be removed until you call the
callback.
These also handle "concurrent" changes. If you "stack" enter/leaves of a single
component before the animation has completed, it will block out all of those
animations until the current animation completes, and then finally it will
animate 0 or 1 times to get itself into the desired current state. This is what
differentiates `componentWillEnter()` from `componentDidMount()`.
The next step would be to build `componentDidReorder()`.
I've built `ReactCSSTransitionGroup` which is identical to the old
`ReactTransitionGroup` and codemodded the callsites.
In the case of having an animated node which is, after the leave-transition has been activated, then re-added in a render call causes React to 'break'. This is especially noticeable if you spam to removal and re-addition of an item in a ReactTransitionGroup.
This fix simply stops the leave transition and restarts the enter transition.
It is valuable to know when the number of children in a TransitionGroup is going
to increase or decrease, since we might want to apply extra animations.
For instance, when used with overflow:auto, we might want to apply different css
based on it overflowing or not - to do this we need to calculate this after new
nodes has entered and after nodes has been removed.
Context is adding another argument that shifts all of them by one. Since we can already use this.getDOMNode(), it doesn't really make sense to pass it as an argument to that function.
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'}
}
});
This introduces `ReactLink` which is a super lightweight way to do two-way binding for React.
If you want to use a controlled form input today, it's a lot of lines of code:
http://jsfiddle.net/T3z3v/
Look how many times `name` is repeated in there. And you have to remember to wire up event handles and pass the right state and
right event handler for *each* form field. It's really annoying.
With ReactLink, you can "link" a form value to a state field. It's just some simple sugar around the value prop/onChange
convention:
https://gist.github.com/petehunt/6689857
Ah, much nicer! And requires very little core changes or extra bytes. `ReactLink` just wraps the current value and "request
change" handler into a little object and provides some sugar to create some from composite component state.
This introduces <ReactTransitionGroup>, a component that works a lot
like Angular's ng-animate.
The problem we're currently facing is twofold:
1. We don't really have a great convention surrounding CSS transitions
in React
2. (harder) we can't animate nodes that are leaving the DOM, as their
nodes are instantly destroyed.
To solve the first issue I've adopted Angular's convention. It's
implemented in ReactTransitionableChild.
The second part is what's tricky. To do this I've implemented three modules:
- ReactTransitionableChild, which can keep its old children around if they
change to null
- ReactTransitionKeySet, which can look at a prev and next set of child
keys and merge them in a reasonable way
- ReactTransitionGroup, which combines ReactTransitionableChild and
ReactTransitionKeySet to keep nodes that are leaving the DOM in the
DOM until their animations are complete