React 18 - Transitions
Tags: react, javascript, frontend, news
Published: 2023-03-27 13:11:56

No React 18, foi introduzido um novo recurso chamado Transitions. Transitions é uma API que permite aos desenvolvedores gerenciar animações e transições durante as renderizações, de forma a evitar que o usuário perceba interrupções ou atrasos ao interagir com a interface.

As Transitions do React 18 ajudam a criar experiências de usuário mais suaves e responsivas, permitindo que os desenvolvedores controlem e priorizem a renderização de componentes e atualizações de estado. Isso é especialmente útil quando há muitas mudanças no DOM, como em casos de carregamento de dados, atualizações em tempo real ou animações complexas.

A API de Transitions introduz o hook useTransition, que pode ser usado para definir e controlar uma transição. O useTransition retorna um array com dois elementos: o primeiro é uma função que pode ser usada para iniciar uma transição, e o segundo é um booleano que indica se a transição está ativa ou não.

Aqui está um exemplo básico de como usar o useTransition:

```
import { useState, useTransition } from "react";

function App() {
  const [data, setData] = useState(null);
  const [startTransition, isPending] = useTransition();

  const fetchData = async () => {
    startTransition(() => {
      setData(null);
    });

    const response = await fetch("/api/data");
    const result = await response.json();

    startTransition(() => {
      setData(result);
    });
  };

  return (
    <div>
      <button onClick={fetchData}>Carregar dados</button>
      {isPending && <p>Carregando...</p>}
      {data && <div>{JSON.stringify(data)}</div>}
    </div>
  );
}

```
Neste exemplo, a função fetchData é chamada quando o usuário clica no botão "Carregar dados". A transição é iniciada com a função startTransition e, enquanto a transição estiver ativa, o componente exibirá "Carregando...". Quando a transição terminar e os dados forem carregados, o componente exibirá os dados na tela.

As Transitions no React 18 permitem que os desenvolvedores criem experiências de usuário mais fluidas e otimizadas, oferecendo maior controle sobre o processo de renderização e atualização dos componentes.

Vamos criar um exemplo mais complexo usando Transitions no React 18 para gerenciar a exibição de uma lista de itens com animações de entrada e saída. Para isso, utilizaremos a biblioteca react-spring para criar as animações.

Criaremos o componente AnimatedList:

```
import { useState, useTransition } from "react";
import { useTransition as useSpringTransition, animated } from "react-spring";

function AnimatedList() {
  const [items, setItems] = useState([]);
  const [inputValue, setInputValue] = useState("");
  const [startTransition, isPending] = useTransition();

  const transitions = useSpringTransition(items, {
    from: { opacity: 0, transform: "translate3d(0, -40px, 0)" },
    enter: { opacity: 1, transform: "translate3d(0, 0, 0)" },
    leave: { opacity: 0, transform: "translate3d(0, -40px, 0)" },
    config: { duration: 300 },
  });

  const addItem = () => {
    startTransition(() => {
      setItems((prevItems) => [...prevItems, inputValue]);
      setInputValue("");
    });
  };

  const removeItem = (index) => {
    startTransition(() => {
      setItems((prevItems) => prevItems.filter((_, i) => i !== index));
    });
  };

  return (
    <div>
      <input
        type="text"
        value={inputValue}
        onChange={(e) => setInputValue(e.target.value)}
        disabled={isPending}
      />
      <button onClick={addItem} disabled={isPending}>
        Adicionar item
      </button>
      <ul>
        {transitions((style, item, _, index) => (
          <animated.li key={item} style={style} onClick={() => removeItem(index)}>
            {item}
          </animated.li>
        ))}
      </ul>
    </div>
  );
}

export default AnimatedList;

```
Neste exemplo, criamos um componente AnimatedList que permite adicionar e remover itens com animações suaves de entrada e saída. A lista é gerenciada usando o estado items, e as transições são criadas usando a API useTransition do React 18 e a API useTransition do react-spring.

Ao clicar no botão "Adicionar item", a função addItem é chamada e inicia uma transição para adicionar o item à lista. Da mesma forma, ao clicar em um item da lista, a função removeItem é chamada para iniciar uma transição e remover o item. Enquanto a transição estiver ativa, o input e o botão são desabilitados para evitar interações adicionais.

As animações de entrada e saída são definidas no objeto de configuração passado para a função useSpringTransition. Neste caso, os itens da lista são animados com uma mudança de opacidade e uma transformação de posição no eixo Y.

Esse exemplo demonstra como combinar as Transitions do React 18 com animações CSS usando a biblioteca react-spring para criar experiências de usuário mais fluidas e interativas.

Vamos criar o mesmo exemplo usando a biblioteca framer-motion.

```
import { useState, useTransition } from "react";
import { AnimatePresence, motion } from "framer-motion";

function FramerMotionList() {
  const [items, setItems] = useState([]);
  const [inputValue, setInputValue] = useState("");
  const [startTransition, isPending] = useTransition();

  const addItem = () => {
    startTransition(() => {
      setItems((prevItems) => [...prevItems, inputValue]);
      setInputValue("");
    });
  };

  const removeItem = (index) => {
    startTransition(() => {
      setItems((prevItems) => prevItems.filter((_, i) => i !== index));
    });
  };

  return (
    <div>
      <input
        type="text"
        value={inputValue}
        onChange={(e) => setInputValue(e.target.value)}
        disabled={isPending}
      />
      <button onClick={addItem} disabled={isPending}>
        Adicionar item
      </button>
      <ul>
        <AnimatePresence>
          {items.map((item, index) => (
            <motion.li
              key={item}
              initial={{ opacity: 0, y: -20 }}
              animate={{ opacity: 1, y: 0 }}
              exit={{ opacity: 0, y: -20 }}
              transition={{ duration: 0.3 }}
              onClick={() => removeItem(index)}
            >
              {item}
            </motion.li>
          ))}
        </AnimatePresence>
      </ul>
    </div>
  );
}

export default FramerMotionList;

```

Neste exemplo, criamos um componente FramerMotionList que permite adicionar e remover itens com animações suaves de entrada e saída. A lista é gerenciada usando o estado items, e as transições são criadas usando a API useTransition do React 18 e a API AnimatePresence e motion do framer-motion.

Ao clicar no botão "Adicionar item", a função addItem é chamada e inicia uma transição para adicionar o item à lista. Da mesma forma, ao clicar em um item da lista, a função removeItem é chamada para iniciar uma transição e remover o item. Enquanto a transição estiver ativa, o input e o botão são desabilitados para evitar interações adicionais.

As animações de entrada e saída são definidas nos objetos initial, animate e exit dos componentes motion.li. Neste caso, os itens da lista são animados com uma mudança de opacidade e uma transformação de posição no eixo Y.

Esse exemplo demonstra como combinar as Transitions do React 18 com animações CSS usando a biblioteca framer-motion para criar experiências de usuário mais fluidas e interativas.