Categories
React

React Transition Group — SwitchTransition and TransitionGroup

With the react-spring library, we can render animations in our React app easily.

In this article, we’ll take a look at how to get started with the React Transition Group.

SwitchTransition

The SwitchTransition component lets us control render between state transitions.

For example, we can write:

App.js

import React, { useState } from "react";
import { CSSTransition, SwitchTransition } from "react-transition-group";
import "./styles.css";

export default function App() {
  const [state, setState] = useState(false);

  return (
    <div className="App">
      <SwitchTransition>
        <CSSTransition
          key={state ? "Goodbye, world!" : "Hello, world!"}
          addEndListener={(node, done) =>
            node.addEventListener("transitionend", done, false)
          }
          classNames="fade"
        >
          <button onClick={() => setState((state) => !state)}>
            {state ? "Goodbye, world!" : "Hello, world!"}
          </button>
        </CSSTransition>
      </SwitchTransition>
    </div>
  );
}

styles.css

fade-enter {
  opacity: 0;
}
.fade-exit {
  opacity: 1;
}
.fade-enter-active {
  opacity: 1;
}
.fade-exit-active {
  opacity: 0;
}
.fade-enter-active,
.fade-exit-active {
  transition: opacity 500ms;
}

We add the SwitchTransition and CSSTransition components to let us add transitions with external CSS styles.

The SwitchTransition component lets us render transitions when we toggle the state state.

CSSTransition shows the styles for each state transition.

The addEndListener prop has a function that calls done to end the transition.

TransitionGroup

The TransitionGroup component lets us manage a set of transition components.

For example, we can use it by writing:

App.js

import React, { useState } from "react";
import { CSSTransition, TransitionGroup } from "react-transition-group";
import { v4 as uuidv4 } from "uuid";
import "./styles.css";

export default function App() {
  const [items, setItems] = useState([
    { id: uuidv4(), text: "eat" },
    { id: uuidv4(), text: "drink" },
    { id: uuidv4(), text: "sleep" },
    { id: uuidv4(), text: "walk" }
  ]);
  return (
    <div className="App">
      <TransitionGroup className="todo-list">
        {items.map(({ id, text }) => (
          <CSSTransition key={id} timeout={500} classNames="item">
            <div>
              <button
                className="remove-btn"
                variant="danger"
                size="sm"
                onClick={() =>
                  setItems((items) => items.filter((item) => item.id !== id))
                }
              >
                &times;
              </button>
              {text}
            </div>
          </CSSTransition>
        ))}
      </TransitionGroup>
    </div>
  );
}

styles.css

.remove-btn {
  margin-right: 0.5rem;
}

.item-enter {
  opacity: 0;
}
.item-enter-active {
  opacity: 1;
  transition: opacity 500ms ease-in;
}
.item-exit {
  opacity: 1;
}
.item-exit-active {
  opacity: 0;
  transition: opacity 500ms ease-in;
}

We have an items state that has an array of items as its initial value.

Then we use that with the TransitionGroup component to display transitions for each item rendered inside it.

Inside it, we have th CSSTransition component to render the transition according to the styles.

When we click on the button, we remove the current item by calling setItems function.

Now when we click on the ‘x’, we see the transition as the item disappears.

Conclusion

We can add transitions to a group of items with the TransitionGroup component.

The SwitchTransition lets us render transitions between state changes.

Categories
React

React Transition Group — SwitchTransition and TransitionGroup

With the react-spring library, we can render animations in our React app easily.

In this article, we’ll take a look at how to get started with the React Transition Group.

SwitchTransition

The SwitchTransition component lets us control render between state transitions.

For example, we can write:

App.js

import React, { useState } from "react";
import { CSSTransition, SwitchTransition } from "react-transition-group";
import "./styles.css";

export default function App() {
  const [state, setState] = useState(false);

  return (
    <div className="App">
      <SwitchTransition>
        <CSSTransition
          key={state ? "Goodbye, world!" : "Hello, world!"}
          addEndListener={(node, done) =>
            node.addEventListener("transitionend", done, false)
          }
          classNames="fade"
        >
          <button onClick={() => setState((state) => !state)}>
            {state ? "Goodbye, world!" : "Hello, world!"}
          </button>
        </CSSTransition>
      </SwitchTransition>
    </div>
  );
}

styles.css

fade-enter {
  opacity: 0;
}
.fade-exit {
  opacity: 1;
}
.fade-enter-active {
  opacity: 1;
}
.fade-exit-active {
  opacity: 0;
}
.fade-enter-active,
.fade-exit-active {
  transition: opacity 500ms;
}

We add the SwitchTransition and CSSTransition components to let us add transitions with external CSS styles.

The SwitchTransition component lets us render transitions when we toggle the state state.

CSSTransition shows the styles for each state transition.

The addEndListener prop has a function that calls done to end the transition.

TransitionGroup

The TransitionGroup component lets us manage a set of transition components.

For example, we can use it by writing:

App.js

import React, { useState } from "react";
import { CSSTransition, TransitionGroup } from "react-transition-group";
import { v4 as uuidv4 } from "uuid";
import "./styles.css";

export default function App() {
  const [items, setItems] = useState([
    { id: uuidv4(), text: "eat" },
    { id: uuidv4(), text: "drink" },
    { id: uuidv4(), text: "sleep" },
    { id: uuidv4(), text: "walk" }
  ]);
  return (
    <div className="App">
      <TransitionGroup className="todo-list">
        {items.map(({ id, text }) => (
          <CSSTransition key={id} timeout={500} classNames="item">
            <div>
              <button
                className="remove-btn"
                variant="danger"
                size="sm"
                onClick={() =>
                  setItems((items) => items.filter((item) => item.id !== id))
                }
              >
                &times;
              </button>
              {text}
            </div>
          </CSSTransition>
        ))}
      </TransitionGroup>
    </div>
  );
}

styles.css

.remove-btn {
  margin-right: 0.5rem;
}

.item-enter {
  opacity: 0;
}
.item-enter-active {
  opacity: 1;
  transition: opacity 500ms ease-in;
}
.item-exit {
  opacity: 1;
}
.item-exit-active {
  opacity: 0;
  transition: opacity 500ms ease-in;
}

We have an items state that has an array of items as its initial value.

Then we use that with the TransitionGroup component to display transitions for each item rendered inside it.

Inside it, we have the CSSTransition component to render the transition according to the styles.

When we click on the button, we remove the current item by calling setItems function.

Now when we click on the ‘x’, we see the transition as the item disappears.

Conclusion

We can add transitions to a group of items with the TransitionGroup component.

The SwitchTransition lets us render transitions between state changes.

Categories
React

Add Animation with the React Transition Group Library

With the react-spring library, we can render animations in our React app easily.

In this article, we’ll take a look at how to get started with the React Transition Group.

Getting Started

We can install the library by running:

npm install react-transition-group --save

with NPM or:

yarn add react-transition-group

with Yarn.

Transition

We can add transitions by using the Transition component.

For example, we can write:

import React, { useState } from "react";
import { Transition } from "react-transition-group";

const duration = 300;

const defaultStyle = {
  transition: `opacity ${duration}ms ease-in-out`,
  opacity: 0
};

const transitionStyles = {
  entering: { opacity: 1 },
  entered: { opacity: 1 },
  exiting: { opacity: 0 },
  exited: { opacity: 0 }
};

const Fade = ({ in: inProp }) => (
  <Transition in={inProp} timeout={duration}>
    {(state) => (
      <div
        style={{
          ...defaultStyle,
          ...transitionStyles[state]
        }}
      >
        I'm a fade Transition!
      </div>
    )}
  </Transition>
);

export default function App() {
  const [show, setShow] = useState(false);

  return (
    <div className="App">
      <button onClick={() => setShow(!show)}>toggle</button>
      <Fade in={show} />
    </div>
  );
}

We create the Fade component with the Transition component inside it to create the transition.

We set the defaultStyle to set the default style.

Then transitionStyles has the styles to add based on the transition state.

The 2 styles together lets us apply the styles dynamically for to create the fade transition.

In the App component, we have the button to toggle the show state.

Then in the Fade transition, we pass the show state as the value of the in prop to show the enter transition when show is true .

The timeout sets the duration of the transition.

Now when we click on the toggle button, we see the item text toggled with the fade transition.

CSSTransition

The CSSTransition component lets us animate components with external CSS.

For example, we can write:

App.js

import React, { useState } from "react";
import { CSSTransition } from "react-transition-group";
import "./styles.css";

export default function App() {
  const [show, setShow] = useState(false);

  return (
    <div className="App">
      <button type="button" onClick={() => setShow(!show)}>
        toggle
      </button>
      <CSSTransition in={show} timeout={200} classNames="my-node">
        <div>I'll receive my-node-* classes</div>
      </CSSTransition>
    </div>
  );
}

styles.css

.my-node-enter {
  opacity: 0;
}
.my-node-enter-active {
  opacity: 1;
  transition: opacity 200ms;
}
.my-node-exit {
  opacity: 1;
}
.my-node-exit-active {
  opacity: 0;
  transition: opacity 200ms;
}

We have the show state again.

And we add the styles for each stage of the transition with the styles.css file.

The CSSTransition component takes the in prop as it does with the Transition component.

timeout has the duration of the transition duration.

classNames has the class name prefix for the transition.

Now when we click on the toggle button, we see the item text flash.

Conclusion

We can add transition effects easily with the React Transition Group library.

Categories
Vue 3

Vue 3 — More Complex Props

Vue 3 is the up and coming version of Vue front end framework.

It builds on the popularity and ease of use of Vue 2.

In this article, we’ll look at how to use props with Vue 3.

Passing a Number

We can pass in numbers to props.

For instance, we can write:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://unpkg.com/vue@next"></script>
  </head>
  <body>
    <div id="app">
      <blog-post v-for="post of posts" :likes="post.likes"></blog-post>
    </div>
    <script>
      const app = Vue.createApp({
        data() {
          return {
            posts: [{ title: "hello world", author: "james", likes: 100 }]
          };
        }
      }); 
      app.component("blog-post", {
        props: {
          likes: Number
        },
        template: `<p>{{likes}}</p>`
      }); 
      app.mount("#app");
    </script>
  </body>
</html>

to create the blog-post component that takes the likes prop.

likes is a number, so we’ve to put the : before the likes to let us pass in an expression.

We can also pass in a number literal:

<blog-post :likes="100"></blog-post>

Passing a Boolean

To pass in a boolean, we can write:

<blog-post is-published></blog-post>

to pass in true to the is-published prop.

To pass in false , we’ve write out the whole expression:

<blog-post :is-published='false'></blog-post>

And we can pass in other expressions.

Passing an Array

We can pass in an array literal as a prop value.

So we can write:

<blog-post :comment-ids="[1, 2, 3]"></blog-post>

or we can write:

<blog-post :comment-ids="post.commentIds"></blog-post>

Passing an Object

Vue props can take objects.

So we can write:

<blog-post
  :author="{
    firstName: 'james',
    lastName: 'smith'
  }"
></blog-post>

We pass in an object to the author prop.

The : tells Vue that the object isn’t a string.

We can also pass in another expression that returns an object.

Passing the Properties of an Object

To pass in the properties of an object as props, we can use the v-bind without the argument.

For example, we can write:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://unpkg.com/vue@next"></script>
  </head>
  <body>
    <div id="app">
      <blog-post v-for="post of posts" v-bind="post"></blog-post>
    </div>
    <script>
      const app = Vue.createApp({
        data() {
          return {
            posts: [{ title: "hello world", author: "james", likes: 100 }]
          };
        }
      }); 
      app.component("blog-post", {
        props: {
          title: String,
          author: String,
          likes: Number
        },
        template: `
          <div>
            <h1>{{title}}</h1>
            <p>author: {{author}}</p>
            <p>likes: {{likes}}</p>
          </div>
        `
      }); 
      app.mount("#app");
    </script>
  </body>
</html>

Then the properties of post will be passed into blog-post as prop values.

The property names are the prop names.

This is a shorthand for:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://unpkg.com/vue@next"></script>
  </head>
  <body>
    <div id="app">
      <blog-post
        v-for="post of posts"
        :title="post.title"
        :author="post.author"
        :likes="post.likes"
      ></blog-post>
    </div>
    <script>
      const app = Vue.createApp({
        data() {
          return {
            posts: [{ title: "hello world", author: "james", likes: 100 }]
          };
        }
      }); 
      app.component("blog-post", {
        props: {
          title: String,
          author: String,
          likes: Number
        },
        template: `
          <div>
            <h1>{{title}}</h1>
            <p>author: {{author}}</p>
            <p>likes: {{likes}}</p>
          </div>
        `
      }); 
      app.mount("#app");
    </script>
  </body>
</html>

As we can see, it’s much longer and a lot more repetitive than the shorthand.

Conclusion

We can pass in various kinds of data easily with Vue components.

We just need to use v-bind or : for short.

Categories
React

Animate with the react-spring Library — Parallax Scrolling and Performance

With the react-spring library, we can render animations in our React app easily.

In this article, we’ll take a look at how to get started with react-spring.

Parallax

The Parallax component lets us create a scroll container.

Inside it, we add the ParallaxLayer component to let react-spring take care of moving them.

For example, we can write:

import React from "react";
import { Parallax, ParallaxLayer } from "react-spring/renderprops-addons";

export default function App() {
  return (
    <div>
      <Parallax
        pages={2}
        scrolling={false}
        horizontal
        ref={(ref) => (this.parallax = ref)}
      >
        <ParallaxLayer
          offset={0}
          speed={0.1}
          onClick={() => this.parallax.scrollTo(1)}
          style={{
            display: "flex",
            alignItems: "center",
            justifyContent: "center"
          }}
        >
          <img
            src="https://i.picsum.photos/id/23/200/300.jpg?hmac=NFze_vylqSEkX21kuRKSe8pp6Em-4ETfOE-oyLVCvJo"
            style={{ width: "20%" }}
          />
        </ParallaxLayer>

<ParallaxLayer
          offset={1}
          speed={0.1}
          onClick={() => this.parallax.scrollTo(0)}
          style={{
            display: "flex",
            alignItems: "center",
            justifyContent: "center"
          }}
        >
          <img
            src="https://i.picsum.photos/id/24/200/300.jpg?hmac=UogR0hFxP5yLDwcZpCawObw8Bzm9vnzci_7eMrbqn_s"
            style={{ width: "40%" }}
          />
        </ParallaxLayer>
      </Parallax>
    </div>
  );
}

to add images into our page.

When we click it, the this.parallax.scrollTo method runs, and we’ll go to the image with the given offset.

Improve Performance

We can improve performance with various tweaks.

We can add the native flag with expensive animations to improve animation performance.

For example, we can write:

import React from "react";
import { Spring, animated } from "react-spring/renderprops";

export default function App() {
  return (
    <div>
      <Spring native from={{ opacity: 0 }} to={{ opacity: 1 }}>
        {(props) => <animated.div style={props}>hello</animated.div>}
      </Spring>
    </div>
  );
}

We add the native prop to improve the performance of our animation.

This prop can also be used for inner text animation:

import React from "react";
import { Spring, animated } from "react-spring/renderprops";

export default function App() {
  return (
    <div>
      <Spring native from={{ number: 0 }} to={{ number: 1 }}>
        {(props) => <animated.div>{props.number}</animated.div>}
      </Spring>
    </div>
  );
}

And we can use it with scrolling animation:

import React from "react";
import { Spring, animated } from "react-spring/renderprops";

export default function App() {
  return (
    <div>
      <Spring native from={{ scroll: 0 }} to={{ scroll: 250 }}>
        {(props) => (
          <animated.div
            scrollTop={props.scroll}
            style={{ overflowY: "scroll", height: 300 }}
          >
            {Array(100)
              .fill()
              .map((_, i) => (
                <p key={i}>{i}</p>
              ))}
          </animated.div>
        )}
      </Spring>
    </div>
  );
}

We can also use it with Trail and Transition components.

Interpolation

We can also use the native prop with interpolation.

For example, we can write:

import React from "react";
import { Spring, animated, interpolate } from "react-spring/renderprops";

export default function App() {
  return (
    <div>
      <Spring
        native
        from={{ o: 0, xyz: [0, 0, 0], color: "red" }}
        to={{ o: 1, xyz: [10, 20, 5], color: "green" }}
      >
        {({ o, xyz, color }) => (
          <animated.div
            style={{
              color,
              background: o.interpolate((o) => `rgba(210, 57, 77, ${o})`),
              transform: xyz.interpolate(
                (x, y, z) => `translate3d(${x}px, ${y}px, ${z}px)`
              ),
              border: interpolate(
                [o, color],
                (o, c) => `${o * 10}px solid ${c}`
              ),
              padding: o
                .interpolate({ range: [0, 0.5, 1], output: [0, 0, 10] })
                .interpolate((o) => `${o}%`),
              opacity: o.interpolate([0.1, 0.2, 0.6, 1], [1, 0.1, 0.5, 1])
            }}
          >
            {o.interpolate((n) => n.toFixed(2))}
          </animated.div>
        )}
      </Spring>
    </div>
  );
}

We pass in a function to let us interpolate the styles for animation with the interpolate method.

And we add the native prop to speed that up.

Conclusion

We can add the native prop to speed up our react-spring animation.

Also, we can add parallax scrolling with the Parallax component.