gpt4 book ai didi

reactjs - 如何使用react-transition-group触发动画

转载 作者:行者123 更新时间:2023-12-03 13:49:21 25 4
gpt4 key购买 nike

问题是我有一个具有三种状态的表单:错误、信息和成功。根据服务器的响应,使用上述状态触发 toastr ,当服务器的响应可用时,我需要添加淡入淡出动画。

toasterService.js

 import React, {useState} from 'react';
import {Transition} from 'react-transition-group';
import './toasterService.css'

export default function ToasterService(content, timeout, style) {
const inProp = useState(true); // always call hook on top level
const duration = timeout;
const transitionStyles = {
entering: {opacity: 1},
entered: {opacity: 1},
exiting: {opacity: 0},
exited: {opacity: 0},
};

let defaultStyle = {};

switch (style) {
case 'info' :
defaultStyle = {
transition: `opacity ${duration}ms ease-in-out`,
opacity: 0,
backgroundColor: '#00c5dc',
color: '#ffffff'
};
break;

case 'success' :
defaultStyle = {
transition: `opacity ${duration}ms ease-in-out`,
opacity: 0,
backgroundColor: '#8ebe4b',
color: '#ffffff'
};
break;
case 'danger' :
defaultStyle = {
transition: `opacity ${duration}ms ease-in-out`,
opacity: 0,
backgroundColor: '#FF0000',
color: '#ffffff'
};
break;
default :
}


return (<div className="main-alert">

<Transition in={inProp} timeout={duration}>
{state => (
<div style={{
...defaultStyle,
...transitionStyles[state]
}}>
{content}
</div>
)}
</Transition>
</div>

);
}

登录.js

import ToastService from '../../services/core/toasterService';
// on click of login btn
socialSignIn = () => {
let obj = {};
obj = this.state;

fetch(url,
{
method: 'post',
body: JSON.stringify(obj)

}).then(function (res) {
console.log(res.json());
ToastService('success', 5000,'info');
return res.json();

})
};

Toast 服务接收 3 个参数,但 toastr 未出现。我缺少什么?

最佳答案

我最近自己构建了一个 Toastr 组件,使用 styled-componentsanimejsreact-transition-group 提供基本功能,这可能会有所帮助你做对了。

注意:我认为使用 animejs 比为过渡的每个阶段设置样式更容易。您基本上可以获取进入或退出元素的引用,并使用 animejs 按照您喜欢的方式为其设置动画。

react-transition-group 将为您提供对这些属性中元素的引用:

<Transition
key={item.id}
onEntering={animateEnter} // animateEnter will have a reference to the element
onExiting={animateExit} // animateExist will have a reference to the element
timeout={{
enter: 500,
exit: 500
}}
unmountOnExit={true} // I was testing, but I don't think this prop is necessary in my component
>

See working example on CodeSandbox

enter image description here

这是代码:

index.js

import React from "react";
import ReactDOM from "react-dom";
import Toastr from "./Toastr";
import SomeComponent from "./SomeComponent";

import "./styles.css";

function App() {
return (
<Toastr>
<SomeComponent />
</Toastr>
);
}

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

Toastr.js

import React, { useRef, useEffect, useState } from "react";
import styled from "styled-components";
import { TransitionGroup, Transition } from "react-transition-group";
import anime from "animejs";
import ToastrContext from "./ToastrContext";

// CREATE A USE TOASTER HOOK ?
// MAYBE CREATE AN APP STATE TO STORE THE TOASTS

const S = {};

S.FixedContainer = styled.div`
position: fixed;
bottom: 10px;
/* right: 5px; */
/* left: 0; right: 0; */
/* CENTER IT HORIZONTALLY */
left: 50%;
transform: translateX(-50%);
`;

S.ToastContainer = styled.div`
width: 300px;
height: 64px;
margin-top: 10px;
margin-bottom: 10px;
/* padding-left: 10px; */
color: white;
font-weight: bold;
background: #39c16c;
border-radius: 5px;
display: flex;
align-items: center;
justify-content: center;
`;

function Toastr(props) {
const lastToastLengthRef = useRef(0);
const [toasts, setToasts] = useState([]);
const toastID = useRef(0);

console.log("Toastr rendering...");
console.log(toasts);

function addNewToast(toast) {
setToasts(prevState => {
const aux = Array.from(prevState);
aux.push({ msg: toast, id: toastID.current });
toastID.current = toastID.current + 1;
return aux;
});
}

useEffect(() => {
if (toasts.length > lastToastLengthRef.current) {
console.log("useEffect: Toast was added...");
// TOAST WAS ADDED
setTimeout(() => {
setToasts(prevState => {
const aux = Array.from(prevState);
aux.shift();
return aux;
});
}, 1000);
lastToastLengthRef.current = toasts.length;
return;
}
lastToastLengthRef.current = toasts.length;
}, [toasts]);

function animateEnter(element) {
anime({
targets: element,
opacity: 0,
duration: 0
});
anime({
targets: element,
opacity: 1,
easing: "easeOutExpo",
duration: 2000
});
}

function animateExit(element) {
anime({
targets: element,
opacity: 0,
easing: "easeOutExpo",
duration: 2000
});
}

// const toastItems = toasts.map((item,index) =>
// <S.ToastContainer key={item.id}>{item.msg}</S.ToastContainer>
// );

const toastItems = toasts.map((item, index) => (
<Transition
key={item.id}
onEntering={animateEnter}
onExiting={animateExit}
timeout={{
enter: 500,
exit: 500
}}
unmountOnExit={true}
>
<S.ToastContainer>{item.msg}</S.ToastContainer>
</Transition>
));

return (
<React.Fragment>
<S.FixedContainer>
<TransitionGroup component={null}>{toastItems}</TransitionGroup>
{/* {toastItems} */}
</S.FixedContainer>
<ToastrContext.Provider value={addNewToast}>
{props.children}
</ToastrContext.Provider>
</React.Fragment>
);
}

// Toastr.whyDidYouRender = true;

export default Toastr;

ToastrContext.js

import React from "react";

const ToastrContext = React.createContext(null);

export default ToastrContext;

SomeComponent.js(将发出 toasts)

import React, { useContext } from "react";
import ToastrContext from "./ToastrContext";
import styled from "styled-components";

function SomeComponent() {
const sendToast = useContext(ToastrContext);

return (
<React.Fragment>
<div>Hey! Click for some toasts!</div>
<button onClick={() => sendToast("This is your toast!")}>Click</button>
</React.Fragment>
);
}

export default SomeComponent;

关于reactjs - 如何使用react-transition-group触发动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56700647/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com