Как заставить переходы работать каждый раз при нажатии на элемент - PullRequest
0 голосов
/ 02 июня 2019

Я пытаюсь использовать 'useTransition' и 'animated' из библиотеки React-Spring, и у меня возникла проблема, когда она анимируется только в первый раз, а также не активирует отпуск.

Из-за этого я думаю, что это связано с тем, что ключ не обновляется, и я думаю, именно это позволяет рендерить новую анимацию, но я понятия не имею, как получить ключ для обновления других чем обновить страницу.

function App() {
  const [showApplicants, setShowApplicants] = useState(false);
  const [showSpecificApplicant, setShowSpecificApplicant] = useState([]);
  const [applicants, setApplicants] = useState([
    {
      firstName: "Billy",
      background: "Employed",
      id: 1
    },
    {
      firstName: "Sarah",
      background: "Employed",
      id: 2
    },
    {
      firstName: "Vera",
      background: "Student",
      id: 3
    },
    {
      firstName: "Albert",
      background: "Unemployed",
      id: 4
    }
  ]);

  const transitions = useTransition(applicants, item => item.id, {
    from: {
      transform: "translate(-100%, 0)"
    },
    enter: {
      transform: "translate(0%,0)"
    },
    leave: {
      transform: "translate(150%, 0)"
    },
    config: { duration: 3000 }
  });

  const handleApplicants = () => {
    setShowApplicants(!showApplicants);
    setShowSpecificApplicant([]);
  };

  const showDetails = (e, item) => {
    setShowSpecificApplicant(item.id);
  };

  const SpecificApplicant = () => {
    const matchedUser = applicants.find(
      user => user.id === showSpecificApplicant
    );
    return transitions.map(({ item, key, props }) => {
      return showSpecificApplicant === item.id ? (
        <animated.div key={key} style={props}>
          <div
            style={{
              background: "lightblue",
              width: "20%",
              margin: "0 auto",
              textAlign: "center",
              borderRadius: "5px",
              padding: "10px",
              display: "flex",
              flexDirection: "column"
            }}
          >
            <h3 style={{ margin: "0", padding: "0" }}>
              {matchedUser.firstName}
            </h3>
            <p> Current Status: {matchedUser.background}</p>
          </div>
        </animated.div>
      ) : null;
    });
  };

  return (
    <div className="App">
      <h1>Hello</h1>
      <button onClick={handleApplicants}> Show Applicants </button>
      <ul>
        {showApplicants &&
          applicants.map(item => (
            <button onClick={e => showDetails(e, item)}>
              {item.firstName}
            </button>
          ))}
      </ul>
      <SpecificApplicant />
    </div>
  );
}

Я ожидаю, что анимация будет срабатывать каждый раз, когда я щелкаю кандидата, но она анимируется только в первый раз. После этого они просто появляются нормально. Может кто-нибудь показать мне, что я делаю не так.

1 Ответ

0 голосов
/ 02 июня 2019

Переход должен обрабатывать изменение массива.Поэтому измените массив Applicants на массив showSpecificApplicant в useTransition.Таким образом, он будет применять анимацию ввода для новых элементов массива и анимацию выхода для элемента, который вы удалили из массива.

import React, { useState } from 'react';
import ReactDOM from 'react-dom';
import { useTransition, animated } from 'react-spring';
import './styles.css';

function App() {
  const [showApplicants, setShowApplicants] = useState(false);
  const [showSpecificApplicant, setShowSpecificApplicant] = useState([]);
  const [applicants, setApplicants] = useState([
    {
      firstName: 'Billy',
      background: 'Employed',
      id: 1
    },
    {
      firstName: 'Sarah',
      background: 'Employed',
      id: 2
    },
    {
      firstName: 'Vera',
      background: 'Student',
      id: 3
    },
    {
      firstName: 'Albert',
      background: 'Unemployed',
      id: 4
    }
  ]);

  const transitions = useTransition(showSpecificApplicant, item => item.id, {
    from: {
      transform: 'translate(-100%, 0)'
    },
    enter: {
      transform: 'translate(0%,0)'
    },
    leave: {
      transform: 'translate(150%, 0)'
    }
  });

  const handleApplicants = () => {
    setShowApplicants(!showApplicants);
    setShowSpecificApplicant([]);
  };

  const showDetails = (e, item) => {
    setShowSpecificApplicant([item]);
  };

  const SpecificApplicant = () => {
    return transitions.map(({ item: matchedUser, key, props }) => {
      return (
        <animated.div key={key} style={props}>
          <div
            style={{
              background: 'lightblue',
              width: '20%',
              margin: '0 auto',
              textAlign: 'center',
              borderRadius: '5px',
              padding: '10px',
              display: 'flex',
              flexDirection: 'column'
            }}
          >
            <h3 style={{ margin: '0', padding: '0' }}>
              {matchedUser.firstName}
            </h3>
            <p> Current Status: {matchedUser.background}</p>
          </div>
        </animated.div>
      );
    });
  };

  return (
    <div className="App">
      <h1>Hello</h1>
      <button onClick={handleApplicants}> Show Applicants </button>
      <ul>
        {showApplicants &&
          applicants.map(item => (
            <button onClick={e => showDetails(e, item)}>
              {item.firstName}
            </button>
          ))}
      </ul>
      <SpecificApplicant />
    </div>
  );
}

const rootElement = document.getElementById('root');
ReactDOM.render(<App />, rootElement);

Результат вы можете увидеть здесь: https://codesandbox.io/s/jolly-glade-mbzl7

Теперь вы можете изменить стиль кандидатов, чтобы они были в одной строке во время переходов.Если вы добавите position: 'absolute' к объекту from, то вы на правильном пути.

...