将 ReactCSSTransitionGroup 与样式组件一起使用
Using ReactCSSTransitionGroup with styled-component
我正在使用 styled-components instead of tradition way of css. But I don't know how it can work together with ReactCSSTransitionGroup。
基本上,ReactCSSTransitionGroup
在 css 资源中查找某些 class 名称,然后在其整个生命周期中应用于组件。但是,对于 styled-components
,没有任何 class 名称,样式直接应用于组件。
我知道我可以选择不使用 ReactCSSTransitionGroup
因为这两种技术看起来不兼容。但是当我只使用 styled-components
时,似乎我无法在卸载组件时呈现任何动画 - 它是纯粹的 css,无法访问组件的生命周期。
如有任何帮助或建议,我们将不胜感激。
像下面这样在 CSS 中尝试驼峰命名法。
.enter {
}
.enterActive { }
在引导 React 应用程序的地方使用 injectGlobal()
样式组件辅助方法。使用这种方法,您可以像使用传统的 CSS.
一样设置任何 CSS 选择器的样式
首先创建一个 JS 文件,使用 CSS 为 react-transition-group
导出模板文字(请注意,我使用的是 v2.1 新的 class 名称语法):
globalCss.js
const globalCss = `
.transition-classes {
/* The double class name is to add more specifity */
/* so that this CSS has preference over the component one. */
/* Try removing it, you may not need it if properties don't collide */
/* https://www.styled-components.com/docs/advanced#issues-with-specificity */
&-enter&-enter {
}
&-enter&-enter-active {
}
&-exit&-exit {
}
&-exit&-exit-active {
}
}
`;
export default globalCss;
然后在您的入口点文件上:
index.jsx
import { injectGlobal } from "styled-components";
import globalCss from "./globalCss.js";
injectGlobal`${ globalCss }`; // <-- This will do the trick
ReactDOM.render(
<Provider store={ Store } >
<HashRouter >
<Route path="/" component={ Component1 } />
<Route path="/" component={ Component2 } />
</HashRouter>
</Provider>,
document.getElementsByClassName("react-app")[0]
);
但是,如果您只是使用 CSS/SASS/Less 为 react-trasition-group
编写 classes,即使您使用样式组件,它也能正常工作。
您可以在 styled-components 中使用 css 变量选择器。像这样:
const Animation = styled(ReactCSSTransitionGroup)`
${({ transitionName }) => `.${transitionName}-enter`} {
opacity: 0;
}
${({transitionName}) => `.${transitionName}-leave`} {
opacity: 1;
}
`
const animationID = 'some-hashed-text'
const AnimationComponent = props => (
<Animation
transitionName={animationID}
transitionEnterTimeout={0.1}
transitionLeaveTimeout={2000}
>
<div>some content</div>
</Animation>
)
我不想按照另一个答案中的建议使用 injectGlobal
,因为我需要对每个组件进行不同的转换。
事实证明这很简单 - 只需将过渡 类 嵌套在组件的样式中即可:
import React from "react";
import CSSTransitionGroup from 'react-transition-group/CSSTransitionGroup';
import styled from 'styled-components';
const appearDuration = 500;
const transitionName = `example`;
const Container = styled.section`
font-size: 1.5em;
padding: 0;
margin: 0;
&.${transitionName}-appear {
opacity: 0.01;
}
&.${transitionName}-appear-active {
opacity: 1;
transition: opacity ${appearDuration}ms ease-out;
}`;
export default () => {
return (
<CSSTransitionGroup
transitionName={transitionName}
transitionAppear={true}
transitionAppearTimeout={appearDuration}>
<Container>
This will have the appear transition applied!
</Container>
</CSSTransitionGroup>
);
};
请注意,我使用的是较新的 CSSTransitionGroup
,而不是 ReactCSSTransitionGroup
,但它也应该适用。
很棒,但我必须做一些小的改动才能让它发挥作用。我改变了 <CSSTransition>
的属性,并使用一个函数作为它的 child。
请参阅下面的组件示例,该组件会根据状态变化淡出 in/out:
import React, { Component } from "react";
import ReactDOM from "react-dom";
import { CSSTransition } from "react-transition-group";
import styled from "styled-components";
const Box = styled.div`
width: 300px;
height: 300px;
background: red;
transition: opacity 0.3s;
// enter from
&.fade-enter {
opacity: 0;
}
// enter to
&.fade-enter-active {
opacity: 1;
}
// exit from
&.fade-exit {
opacity: 1;
}
// exit to
&.fade-exit-active {
opacity: 0;
}
}`;
export default class App extends Component {
constructor() {
super();
this.state = {
active: true
};
setInterval(() => this.setState({ active: !this.state.active }), 1000);
}
render() {
return (
<CSSTransition
in={this.state.active}
classNames="fade"
timeout={300}
unmountOnExit
>
{() => <Box />}
</CSSTransition>
);
}
}
import React from "react";
import { CSSTransition } from 'react-transition-group';
const styles = theme => ({
'fade-enter':{
opacity: 0,
},
'fade-enter-active':{
opacity: 1,
transition: "opacity 300ms"
},
'fade-exit':{
opacity: 1,
},
'fade-exit-active':{
opacity: 0,
transition: "opacity 300ms"
},
})
class myAnimatedComponent extends React.Component {
constructor(props){
super(props);
}
render(){
let {classes} = this.props;
return (
<CSSTransition
in={this.props.conditionVariable}
classNames={{
enter: classes['fade-enter'],
enterActive: classes['fade-enter-active'],
exit: classes['fade-exit'],
exitActive: classes['fade-exit-active'],
}}
timeout={300}
unmountOnExit>
<span>This will have the transition applied to it!</span>
</CSSTransition>
);
}
};
export default (styles)(myAnimatedComponent);
我不得不使用 classes['fade-enter']
等,因为 React 更改了这个组件中所有 类 的名称,因为我使用了 withStyles
。也正因为如此,当我导出组件时,React 将我的 类 插入到该组件的道具中,这就是为什么我还必须创建一个名为 类 的变量来捕获那些 类。
有一个很棒的博客 post 解释了如何做到这一点:
https://dev.to/terrierscript/styled-component--react-transition-group--very-simple-transition-jja
他们使用 react-transition-group 提供的低级别 Transiton
组件:
http://reactcommunity.org/react-transition-group/transition
// This is overly simplified, but styles change depend on state from Transition
const MyStyledComponent = styled.div`
transform: translateY(${({ state }) => (state === 'exited' ? "0" : "-100%")});
transition: transform 2s;
`
const App = () =>
<Transition in={animate} timeout={500}>
{(state) => (
// state change: exited -> entering -> entered -> exiting -> exited
<MyStyledComponent state={state}>Hello</MyStyledComponent>
)}
</Transition>
我正在使用 styled-components instead of tradition way of css. But I don't know how it can work together with ReactCSSTransitionGroup。
基本上,ReactCSSTransitionGroup
在 css 资源中查找某些 class 名称,然后在其整个生命周期中应用于组件。但是,对于 styled-components
,没有任何 class 名称,样式直接应用于组件。
我知道我可以选择不使用 ReactCSSTransitionGroup
因为这两种技术看起来不兼容。但是当我只使用 styled-components
时,似乎我无法在卸载组件时呈现任何动画 - 它是纯粹的 css,无法访问组件的生命周期。
如有任何帮助或建议,我们将不胜感激。
像下面这样在 CSS 中尝试驼峰命名法。
.enter {
}
.enterActive { }
在引导 React 应用程序的地方使用 injectGlobal()
样式组件辅助方法。使用这种方法,您可以像使用传统的 CSS.
首先创建一个 JS 文件,使用 CSS 为 react-transition-group
导出模板文字(请注意,我使用的是 v2.1 新的 class 名称语法):
globalCss.js
const globalCss = `
.transition-classes {
/* The double class name is to add more specifity */
/* so that this CSS has preference over the component one. */
/* Try removing it, you may not need it if properties don't collide */
/* https://www.styled-components.com/docs/advanced#issues-with-specificity */
&-enter&-enter {
}
&-enter&-enter-active {
}
&-exit&-exit {
}
&-exit&-exit-active {
}
}
`;
export default globalCss;
然后在您的入口点文件上:
index.jsx
import { injectGlobal } from "styled-components";
import globalCss from "./globalCss.js";
injectGlobal`${ globalCss }`; // <-- This will do the trick
ReactDOM.render(
<Provider store={ Store } >
<HashRouter >
<Route path="/" component={ Component1 } />
<Route path="/" component={ Component2 } />
</HashRouter>
</Provider>,
document.getElementsByClassName("react-app")[0]
);
但是,如果您只是使用 CSS/SASS/Less 为 react-trasition-group
编写 classes,即使您使用样式组件,它也能正常工作。
您可以在 styled-components 中使用 css 变量选择器。像这样:
const Animation = styled(ReactCSSTransitionGroup)`
${({ transitionName }) => `.${transitionName}-enter`} {
opacity: 0;
}
${({transitionName}) => `.${transitionName}-leave`} {
opacity: 1;
}
`
const animationID = 'some-hashed-text'
const AnimationComponent = props => (
<Animation
transitionName={animationID}
transitionEnterTimeout={0.1}
transitionLeaveTimeout={2000}
>
<div>some content</div>
</Animation>
)
我不想按照另一个答案中的建议使用 injectGlobal
,因为我需要对每个组件进行不同的转换。
事实证明这很简单 - 只需将过渡 类 嵌套在组件的样式中即可:
import React from "react";
import CSSTransitionGroup from 'react-transition-group/CSSTransitionGroup';
import styled from 'styled-components';
const appearDuration = 500;
const transitionName = `example`;
const Container = styled.section`
font-size: 1.5em;
padding: 0;
margin: 0;
&.${transitionName}-appear {
opacity: 0.01;
}
&.${transitionName}-appear-active {
opacity: 1;
transition: opacity ${appearDuration}ms ease-out;
}`;
export default () => {
return (
<CSSTransitionGroup
transitionName={transitionName}
transitionAppear={true}
transitionAppearTimeout={appearDuration}>
<Container>
This will have the appear transition applied!
</Container>
</CSSTransitionGroup>
);
};
请注意,我使用的是较新的 CSSTransitionGroup
,而不是 ReactCSSTransitionGroup
,但它也应该适用。
<CSSTransition>
的属性,并使用一个函数作为它的 child。
请参阅下面的组件示例,该组件会根据状态变化淡出 in/out:
import React, { Component } from "react";
import ReactDOM from "react-dom";
import { CSSTransition } from "react-transition-group";
import styled from "styled-components";
const Box = styled.div`
width: 300px;
height: 300px;
background: red;
transition: opacity 0.3s;
// enter from
&.fade-enter {
opacity: 0;
}
// enter to
&.fade-enter-active {
opacity: 1;
}
// exit from
&.fade-exit {
opacity: 1;
}
// exit to
&.fade-exit-active {
opacity: 0;
}
}`;
export default class App extends Component {
constructor() {
super();
this.state = {
active: true
};
setInterval(() => this.setState({ active: !this.state.active }), 1000);
}
render() {
return (
<CSSTransition
in={this.state.active}
classNames="fade"
timeout={300}
unmountOnExit
>
{() => <Box />}
</CSSTransition>
);
}
}
import React from "react";
import { CSSTransition } from 'react-transition-group';
const styles = theme => ({
'fade-enter':{
opacity: 0,
},
'fade-enter-active':{
opacity: 1,
transition: "opacity 300ms"
},
'fade-exit':{
opacity: 1,
},
'fade-exit-active':{
opacity: 0,
transition: "opacity 300ms"
},
})
class myAnimatedComponent extends React.Component {
constructor(props){
super(props);
}
render(){
let {classes} = this.props;
return (
<CSSTransition
in={this.props.conditionVariable}
classNames={{
enter: classes['fade-enter'],
enterActive: classes['fade-enter-active'],
exit: classes['fade-exit'],
exitActive: classes['fade-exit-active'],
}}
timeout={300}
unmountOnExit>
<span>This will have the transition applied to it!</span>
</CSSTransition>
);
}
};
export default (styles)(myAnimatedComponent);
我不得不使用 classes['fade-enter']
等,因为 React 更改了这个组件中所有 类 的名称,因为我使用了 withStyles
。也正因为如此,当我导出组件时,React 将我的 类 插入到该组件的道具中,这就是为什么我还必须创建一个名为 类 的变量来捕获那些 类。
有一个很棒的博客 post 解释了如何做到这一点: https://dev.to/terrierscript/styled-component--react-transition-group--very-simple-transition-jja
他们使用 react-transition-group 提供的低级别 Transiton
组件:
http://reactcommunity.org/react-transition-group/transition
// This is overly simplified, but styles change depend on state from Transition
const MyStyledComponent = styled.div`
transform: translateY(${({ state }) => (state === 'exited' ? "0" : "-100%")});
transition: transform 2s;
`
const App = () =>
<Transition in={animate} timeout={500}>
{(state) => (
// state change: exited -> entering -> entered -> exiting -> exited
<MyStyledComponent state={state}>Hello</MyStyledComponent>
)}
</Transition>