使用带有样式组件的 ReactCSSTransitionGroup
Posted
技术标签:
【中文标题】使用带有样式组件的 ReactCSSTransitionGroup【英文标题】:Using ReactCSSTransitionGroup with styled-component 【发布时间】:2017-07-28 09:43:54 【问题描述】:我正在使用 styled-components 而不是传统的 css 方式。但是不知道怎么和ReactCSSTransitionGroup一起工作。
基本上,ReactCSSTransitionGroup
在 css 资源中查找某些类名,然后在组件的整个生命周期中应用到组件。但是,styled-components
没有任何类名,样式直接应用于组件。
我知道我可以选择不使用ReactCSSTransitionGroup
,因为这两种技术看起来不兼容。但是当我只使用styled-components
时,卸载组件时似乎无法渲染任何动画 - 它是纯 css,无法访问组件的生命周期。
感谢任何帮助或建议。
【问题讨论】:
【参考方案1】:我不想像另一个答案中建议的那样使用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 $appearDurationms ease-out;
`;
export default () =>
return (
<CSSTransitionGroup
transitionName=transitionName
transitionAppear=true
transitionAppearTimeout=appearDuration>
<Container>
This will have the appear transition applied!
</Container>
</CSSTransitionGroup>
);
;
请注意,我使用的是较新的 CSSTransitionGroup
,而不是 ReactCSSTransitionGroup
,但它也应该适用。
【讨论】:
【参考方案2】:Mike Goatly's approach 很棒,但我必须进行一些小改动才能使其正常工作。我更改了<CSSTransition>
的props,并使用了一个函数作为它的子函数。
请参阅下面的组件示例,该组件根据状态更改淡入/淡出:
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>
);
【讨论】:
【参考方案3】:您可以在样式组件中使用 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>
)
【讨论】:
这在与transitionAppear
结合使用时对我有用,但我认为这是错误的方法,因为CSSTransitionGroup
旨在保持静态并处理其中的元素。我无法应用任何休假转换,因为如果有条件地呈现整个 CSSTransitionGroup
将被删除【参考方案4】:
使用 injectGlobal()
styled-component 辅助方法来引导您的 React 应用程序。使用这种方法,您可以设置任何 CSS 选择器的样式,就像使用传统 CSS 一样。
首先创建一个 JS 文件,使用您的 CSS 为 react-transition-group
导出模板文字(请不要我使用 v2.1 新类名语法):
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
编写类,即使你使用 styled-components,它也能很好地工作。
【讨论】:
【参考方案5】:有一篇很棒的博客文章解释了如何做到这一点: 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>
【讨论】:
【参考方案6】: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']
等,因为我使用了withStyles
,React 改变了这个组件中所有类的名称。也正因为如此,当我导出组件时,React 会将我的类插入到该组件的 props 中,这就是为什么我还必须创建一个名为 classes 的变量来捕获这些类。
【讨论】:
【参考方案7】:在 CSS 中尝试 camelCase,如下所示。
.enter
.enterActive
【讨论】:
以上是关于使用带有样式组件的 ReactCSSTransitionGroup的主要内容,如果未能解决你的问题,请参考以下文章
使用带有样式组件的 ReactCSSTransitionGroup
如何在反应中使用带有样式组件的 document.getElementById()?