Reactjs 如何使用react transition group触发动画
问题是我的表单有三种状态:错误、信息和成功。根据服务器的响应,我使用上述状态启动烤面包机,当服务器的响应可用时,我需要添加淡入淡出动画 toasterService.jsReactjs 如何使用react transition group触发动画,reactjs,Reactjs,问题是我的表单有三种状态:错误、信息和成功。根据服务器的响应,我使用上述状态启动烤面包机,当服务器的响应可用时,我需要添加淡入淡出动画 toasterService.js import React, {useState} from 'react'; import {Transition} from 'react-transition-group'; import './toasterService.css' export default function ToasterService(
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>
);
}
Toast服务收到3个参数,但烤面包机未出现。我缺少什么?我最近自己构建了一个Toastr组件,它的基本功能是使用
样式化组件
、动画
和反应转换组
,这可能会帮助您正确使用它
注意:我认为使用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
>
SomeComponent.js(将发出祝酒声)
import React,{useContext}来自“React”;
从“/ToastrContext”导入到astrcontext;
从“样式化组件”导入样式化;
函数SomeComponent(){
const sendtoos=useContext(ToastrContext);
返回(
嘿!点击来祝酒!
sendToast(“这是你的吐司!”)}>单击
);
}
导出默认组件;
<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
>
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);
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;
import React from "react";
const ToastrContext = React.createContext(null);
export default ToastrContext;
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;