【问题标题】:How to get transitions to work each time an element is clicked每次单击元素时如何使转换工作
【发布时间】:2019-06-03 04:14:50
【问题描述】:

我正在尝试使用 React-Spring 库中的 'useTransition' 和 'animated',但遇到了一个问题,即它仅在第一次动画时出现,并且也没有激活离开。

从深入研究来看,我认为这与密钥没有更新这一事实有关,我认为这是使新动画能够渲染的原因,但我不知道如何获取密钥来更新其他动画而不是刷新页面。

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>
  );
}

我希望每次单击申请人时都会触发动画,但它仅在第一次时才动画。之后他们就正常出现了。谁能告诉我我做错了什么。

【问题讨论】:

    标签: javascript reactjs react-spring


    【解决方案1】:

    转换必须处理数组的变化。所以在 useTransition 中将申请者数组更改为 showSpecificApplicant 数组。这样,它将为新数组元素应用进入动画,为从数组中删除的元素应用离开动画。

    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 对象,那么您就在正确的轨道上。

    【讨论】:

    • 优秀。谢谢,这真的很有帮助!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-15
    • 1970-01-01
    • 2020-10-07
    • 2020-04-02
    • 1970-01-01
    • 2020-09-12
    相关资源
    最近更新 更多