将ReactCSSTransitionGroup与样式组件一起使用

时间:2017-03-08 00:34:20

标签: css reactjs styled-components

我使用styled-components而不是传统的css方式。但我不知道它如何与ReactCSSTransitionGroup一起工作。

基本上,ReactCSSTransitionGroup在css资源中查找某些类名,然后在整个生命周期中应用于组件。但是,对于styled-components,没有任何类名,样式直接应用于组件。

我知道我可以选择不使用ReactCSSTransitionGroup,因为这两种技术看起来并不兼容。但是当我只使用styled-components时,似乎我无法在卸载组件时渲染任何动画 - 它是纯粹的CSS,无法访问组件的生命周期。

感谢任何帮助或建议。

7 个答案:

答案 0 :(得分:26)

我不想按照另一个答案的建议使用injectGlobal因为我需要为每个组件制作不同的转换。

事实证明这很简单 - 只需将过渡类嵌套在组件的样式中:

import React from "react";
import CSSTransitionGroup from 'react-transition-group/CSSTransitionGroup';
import styled from 'styled-components';

export default () => {
    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;
        }`;


    return (
        <CSSTransitionGroup
            transitionName={transitionName}
            transitionAppear={true}
            transitionAppearTimeout={appearDuration}>
            <Container>
                This will have the appear transition applied!
            </Container>
        </CSSTransitionGroup>
    );
};

请注意,我使用的是较新的CSSTransitionGroup,而不是ReactCSSTransitionGroup,但它也适用于此。

答案 1 :(得分:3)

Mike Goatly's approach很棒,但是我必须进行一些小的更改才能使其正常工作。我更改了<CSSTransition>的道具,并使用了一个函数作为其子项。

有关组件的示例,请参见下文,该组件会根据状态变化淡入/淡出:

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

答案 2 :(得分:2)

使用启动了React应用程序的injectGlobal()样式组件帮助程序方法。使用此方法,您可以设置任何CSS选择器的样式,就像您使用传统的CSS一样。

首先创建一个JS文件,用react-transition-group的CSS导出模板文字(请不要使用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的类,即使您使用样式化组件,它也可以正常运行。

答案 3 :(得分:2)

您可以在样式组件中使用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>
)

答案 4 :(得分:0)

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的变量来捕获这些类的原因。

答案 5 :(得分:0)

有一篇很棒的博客文章,解释了如何做到这一点: 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 :(得分:-5)

尝试使用CSS中的camelCase,如下所示。

.enter {

}
.enterActive { }