Skip to content

Commit

Permalink
Clean up the README and migration guide a bit (#115)
Browse files Browse the repository at this point in the history
  • Loading branch information
taion authored and jquense committed Jul 15, 2017
1 parent 50c336a commit 91f9b86
Show file tree
Hide file tree
Showing 3 changed files with 273 additions and 285 deletions.
257 changes: 257 additions & 0 deletions Migration.md
@@ -0,0 +1,257 @@
# Migration Guide from v1 to v2

_A few notes to help with migrating from v1 to v2._

The `<CSSTransitionGroup>` component has been removed. A `<CSSTransition>` component has been added for use with the new `<TransitionGroup>` component to accomplish the same tasks.

### tl;dr:

- `transitionName` -> `classNames`
- `transitionEnterTimeout` and `transitionLeaveTimeout` -> `timeout={{ exit, enter }}`
- `transitionAppear` -> `appear`
- `transitionEnter` -> `enter`
- `transitionLeave` -> `exit`

## Walkthrough

Let's take the [original docs example](https://github.com/reactjs/react-transition-group/tree/v1-stable/#high-level-api-csstransitiongroup) and migrate it.

Starting with this CSS:

```css
.example-enter {
opacity: 0.01;
}

.example-enter.example-enter-active {
opacity: 1;
transition: opacity 500ms ease-in;
}

.example-leave {
opacity: 1;
}

.example-leave.example-leave-active {
opacity: 0.01;
transition: opacity 300ms ease-in;
}
```

And this component:

```js
class TodoList extends React.Component {
constructor(props) {
super(props);
this.state = {items: ['hello', 'world', 'click', 'me']};
this.handleAdd = this.handleAdd.bind(this);
}

handleAdd() {
const newItems = this.state.items.concat([
prompt('Enter some text')
]);
this.setState({items: newItems});
}

handleRemove(i) {
let newItems = this.state.items.slice();
newItems.splice(i, 1);
this.setState({items: newItems});
}

render() {
const items = this.state.items.map((item, i) => (
<div key={item} onClick={() => this.handleRemove(i)}>
{item}
</div>
));

return (
<div>
<button onClick={this.handleAdd}>Add Item</button>
<CSSTransitionGroup
transitionName="example"
transitionEnterTimeout={500}
transitionLeaveTimeout={300}>
{items}
</CSSTransitionGroup>
</div>
);
}
}
```

The most straightforward way to migrate is to use `<TransitionGroup>` instead of `<CSSTransitionGroup>`:

```diff
render() {
const items = this.state.items.map((item, i) => (
<div key={item} onClick={() => this.handleRemove(i)}>
{item}
</div>
));

return (
<div>
<button onClick={this.handleAdd}>Add Item</button>
- <CSSTransitionGroup
- transitionName="example"
- transitionEnterTimeout={500}
- transitionLeaveTimeout={300}>
+ <TransitionGroup>
{items}
- </CSSTransitionGroup>
+ </TransitionGroup>
</div>
)
}
```

That doesn't get us much, since we haven't included anything to do the animation. For that, we'll need to wrap each item in a `<CSSTransition>`. First, though, let's adjust our CSS:

```diff
.example-enter {
opacity: 0.01;
}

.example-enter.example-enter-active {
opacity: 1;
transition: opacity 500ms ease-in;
}

-.example-leave {
+.example-exit {
opacity: 1;
}

-.example-leave.example-leave-active {
+.example-exit.example-exit-active {
opacity: 0.01;
transition: opacity 300ms ease-in;
}
```

All we did was replace `leave` with `exit`. v2 uses "exit" instead of "leave" to be more symmetric, avoiding awkwardness with English tenses (like with "entered" and "leaved").

Now we add the `<CSSTransition>` component:

```diff
render() {
const items = this.state.items.map((item, i) => (
+ <CSSTransition
+ key={item}
+ classNames="example"
+ timeout={{ enter: 500, exit: 300 }}
+ >
<div onClick={() => this.handleRemove(i)}>
{item}
</div>
+ <CSSTransition>
));

return (
<div>
<button onClick={this.handleAdd}>Add Item</button>
<TransitionGroup>
{items}
</TransitionGroup>
</div>
)
}
```

Note that we replaced `transitionName` with `classNames`. `<CSSTransition>` otherwise has essentially the same signature as `<CSSTransitionGroup>`. We also replaced `transitionEnterTimeout` and `transitionLeaveTimeout` with a single `timeout` prop with an object.

> **Hint:** If your enter and exit timeouts are the same you can use the shorthand `timeout={500}`.
If we want to make this a bit more encapsulated, we can wrap our `<CSSTransition>` into a separate component for reuse later:

```js
const FadeTransition = (props) => (
<CSSTransition
{...props}
classNames="example"
timeout={{ enter: 500, exit: 300 }}
/>
);
```

We can then use it like:

```diff
render() {
const items = this.state.items.map((item, i) => (
- <CSSTransition
- key={item}
- classNames="example"
- timeout={{ enter: 500, exit: 300 }}
- >
+ <FadeTransition>
<div onClick={() => this.handleRemove(i)}>
{item}
</div>
- <CSSTransition>
+ </FadeTransition>
));

return (
<div>
<button onClick={this.handleAdd}>Add Item</button>
<TransitionGroup>
{items}
</TransitionGroup>
</div>
)
}
```

> **Hey!** You may not need `<CSSTransition>` at all! The lower level `<Transition>` component is very flexible and may be easier to work with for simpler or more custom cases. Check out how we migrated [React-Bootstrap](https://react-bootstrap.github.io/)'s simple transitions to v2 for the [`<Collapse>`](https://github.com/react-bootstrap/react-bootstrap/pull/2676/files#diff-4f938f648d04d4859be417d6590ca7c4) and [`<Fade>`](https://github.com/react-bootstrap/react-bootstrap/pull/2676/files#diff-8f766132cbd9f8de55ee05d63d75abd8) components.

## Wrapping `<Transition>` Components

The old `<TransitionGroup>` component managed transitions through custom static lifecycle methods on its children. In v2 we removed that API in favor of requiring that `<TransitionGroup>` be used with a `<Transition>` component, and using traditional prop passing to communicate between the two.

This means that `<TransitionGroup>`s injects their children with `<Transition>`-specific props that _must_ be passed through to the `<Transition>` component for the transition to work.

```js
const MyTransition = ({ children: child, ...props }) => (
// NOTICE THE SPREAD! THIS IS REQUIRED!
<Transition {...props}>
{transitionState => React.cloneElement(child, {
style: getStyleForTransitionState(transitionState)
})}
</Transition>
);

const MyList = () => (
<TransitionGroup>
{items.map(item => (
<MyTransition>{item}</MyTransition>
)}
</TransitionGroup>
);
```
Note how `<MyTransition>` passes all props other than its own to `<Transition>`.
## Lifecycle Callbacks
As noted, child lifecycle methods have been removed. If you do need to do some work when the `<Transition>` changes from one state to another, use the lifecycle callback props.
```js
<Transition
{...props}
onEnter={handleEnter}
onEntering={handleEntering}
onEntered={handleEntered}
onExit={handleExit}
onExiting={handleExiting}
onExited={handleExited}
/>
```
Each callback is called with the DOM node of the transition component. Note also that there are now _three_ states per enter/exit transition instead of the original two. See the [full documentation](https://reactcommunity.org/react-transition-group/#Transition) for more details.
30 changes: 16 additions & 14 deletions README.md
@@ -1,25 +1,27 @@
**ATTENTION!** To address many issues that have come up over the years, the API in v2.0.0 is different from the original React addon.
# react-transition-group [![npm][npm-badge]][npm]

**If you are migrating from `react-addons-transition-group` and `react-addons-css-transition-group`, [read the documentation for 1.x branch instead](https://github.com/reactjs/react-transition-group/tree/v1-stable) which is a drop-in replacement and is still actively maintained.**
> **ATTENTION!** To address many issues that have come up over the years, the API in v2 is different from that in the original React addon.
>
> **For a drop-in replacement for `react-addons-transition-group` and `react-addons-css-transition-group`, use the v1 release, which is still actively maintained. Documentation and code for that release are available on the [`v1-stable`](https://github.com/reactjs/react-transition-group/tree/v1-stable) branch.**
>
> You can send pull requests with v1 bugfixes against the `v1-stable` branch.
You can also send pull requests with 1.x bugfixes against the `v1-stable` branch.
A set of components for managing component states (including mounting and unmounting) over time, specifically designed with animation in mind.

# react-transition-group
## Documentation

A set of components for managing component states (including mounting) over time,
specifically designed with animation in mind.
- [**Main documentation**](https://reactcommunity.org/react-transition-group/)
- [Migration guide from v1](/Migration.md)

Check out the documentation at: [https://reactcommunity.org/react-transition-group/](https://reactcommunity.org/react-transition-group/)

And the Migration details from v1: [https://github.com/reactjs/react-transition-group/blob/master/migration.md](https://github.com/reactjs/react-transition-group/blob/master/migration.md)

### Examples
## Examples

Clone the repo first:

```sh
```
git@github.com:reactjs/react-transition-group.git
```

Then run `npm install` (or `yarn install`), and finally `npm run storybook` to
start a storybook instance you can navigate to in your browser and see some examples
Then run `npm install` (or `yarn`), and finally `npm run storybook` to start a storybook instance that you can navigate to in your browser to see the examples.

[npm-badge]: https://img.shields.io/npm/v/react-transition-group.svg
[npm]: https://www.npmjs.org/package/react-transition-group

0 comments on commit 91f9b86

Please sign in to comment.