Как мы можем анимировать отображение записей с помощью react-spring

#reactjs #react-hooks #react-spring

Вопрос:

Как мы можем анимировать отображение записей с помощью react-spring . Можем ли мы вызвать функцию useTransition in useEffect() ? Я хотел бы анимировать записи снизу вверх одну за другой, когда пользователь переходит на страницу. Я пробовал ниже, ничего не происходит..? Любой совет был бы действительно полезен.

https://codesandbox.io/s/inspiring-snowflake-34dpx?file=/src/App.js:711-881

 import { useEffect, useState } from "react";
import { useTransition, animated } from "react-spring";

import "./styles.css";

const array1 = [
  { id: "1", name: "Cat" },
  { id: "2", name: "Dog" },
  { id: "3", name: "Cow" }
];
export default function App() {
  const [list, setList] = useState(array1);
  const height = 20;
  useEffect(() => {
    setList(array1);
  }, []);

  const transitions = useTransition(
    Object.entries(list).map((data, i) => ({ ...data, y: i * height })),
    {
      from: { position: "absolute", opacity: 0 },
      enter: { height: 0, opacity: 1 },
      leave: { opacity: 0 },
      config: { tension: 220, friction: 120 }
    }
  );

  return (
    <div className="App">
      {/* {Object.entries(list).map((item, index) => (
        <div key={item.id} className="record">
          <span key={item.name}>{item.name}</span>
        </div>
      ))} */}

      {Object.entries(transitions).map(({ item, props, key }) => (
        <animated.div key={key} style={{ ...props, position: "absolute" }}>
          <div key={item.id} className="record">
            <span key={item.name}>{item.name}</span>
          </div>
        </animated.div>
      ))}
    </div>
  );
}
 

Ответ №1:

transitions Переменная-это функция, поэтому вы не хотите Object.entries(transitions).map() . Это не ошибка, потому что функции в Javascript также являются объектами, но это ничего не даст, потому что массив записей является пустым массивом.

Вы хотите вызвать transitions функцию, которая является своего рода картографом.

 {transitions((props, item, key) => (
 

Ну а теперь я вижу голубую коробку вместо белого экрана. Так что это небольшой прогресс, но еще многое предстоит сделать.

Если вы console.log выберете свой item объект, вы увидите, что он выглядит неправильно.

 Object.entries(list).map((data, i) => ({ ...data, y: i * height }))
 

Вы сопоставляете массив записей объекта, поэтому data переменная представляет собой массив, содержащий ключ и значение. Ты этого не хочешь. list это уже массив, так что бросьте Object.entries .

 list.map((data, i) => ({ ...data, y: i * height })),
 

Теперь я вижу «Корову»! Но два других скрыты, потому что ваши предметы появляются друг над другом.

Вы используете абсолютное позиционирование, но не передали позицию компоненту. Поскольку вы не анимируете это значение, это свойство item скорее чем props .

 <animated.div key={key} style={{ ...props, position: "absolute", top: item.y }}>
 

Теперь я вижу всех троих!

Но перекрывающиеся фоновые блоки, вероятно, не то, что вы предполагали. Я не уверен, что вы имели в виду на самом деле, потому что у вас есть a height 20 в вашем JS и 100px в вашем CSS. У вас также есть height свойство в вашей анимации, но оно ничего не делает.

Все элементы вашего списка имеют height: 0px , потому что вы задаете высоту 0 в enter свойстве, которое вызывается, когда элемент впервые входит в список. С другой стороны, from свойство задает начальные значения, от которых элемент анимируется, поэтому, возможно, вы хотите иметь начальное значение height: 0 in from и некоторое конечное значение height in enter .

Вы можете анимировать высоту фона, но это не повлияет на высоту текста. Возможно, вам захочется transform что-то подобное scaleY . Вы можете использовать преобразование вместо анимации высоты (все элементы начинаются в их конечном положении и растут на месте) или рядом с анимацией высоты (все элементы начинаются вместе вверху и растут вниз).


Вот один из возможных эффектов: Ссылка на песочницу кода

style.css

 .App {
  font-family: sans-serif;
  text-align: center;
}
.record {
  width: 300px;
  background-color: aqua;
  margin: 20px 0;
  color: #1f1d1d;
}
.title {
  font-size: 30px;
  padding: 35px;
}
 

App.js

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

import "./styles.css";

const array1 = [
  { id: "1", name: "Cat" },
  { id: "2", name: "Dog" },
  { id: "3", name: "Cow" }
];

export default function App() {
  const [list, setList] = useState(array1);

  const transitions = useTransition(list, {
    from: { opacity: 0, scaleY: 0 },
    enter: { opacity: 1, scaleY: 1 },
    leave: { opacity: 0 },
    config: { tension: 220, friction: 120 }
  });

  return (
    <div className="App">
      {transitions((props, item, key) => {
        console.log(props, item, key);
        return (
          <animated.div key={key} style={{ ...props }} className="record">
            <div className="title">{item.name}</div>
          </animated.div>
        );
      })}
    </div>
  );
}
 

Редактировать

Как и было запрошено, снизу вверх один за другим:

 export default function App() {
  const height = window.innerHeight;

  const [list, setList] = useState(array1);

  const transitions = useTransition(list, {
    from: { opacity: 0, translateY: height },
    enter: { opacity: 1, translateY: 0 },
    leave: { opacity: 0 },
    config: { tension: 220, friction: 120 },
    trail: 200
  });

  return (
    <div className="App">
      {transitions((props, item, key) => {
        console.log(props, item, key);
        return (
          <animated.div key={key} style={{ ...props }} className="record">
            <div className="title">{item.name}</div>
          </animated.div>
        );
      })}
    </div>
  );
}
 

Комментарии:

1. ..Большое вам спасибо, может ли что-то двигаться от нижней части страницы к верхней ..один за другим other…is это возможно ?

2. Да, но для этого может потребоваться знать высоту документа?. Вы можете использовать абсолютное положение или преобразование перевода для движения. Для «одного за другим» вы можете использовать trail свойство.