【问题标题】:Using ReactCSSTransitionGroup with styled-component使用带有样式组件的 ReactCSSTransitionGroup
【发布时间】:2017-07-28 09:43:54
【问题描述】:

我正在使用 styled-components 而不是传统的 css 方式。但是不知道怎么和ReactCSSTransitionGroup一起工作。

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

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

感谢任何帮助或建议。

【问题讨论】:

    标签: css reactjs styled-components


    【解决方案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 ${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,但它也应该适用。

    【讨论】:

      【解决方案2】:

      Mike Goatly's approach 很棒,但我必须进行一些小改动才能使其正常工作。我更改了&lt;CSSTransition&gt; 的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 { }
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2018-10-16
                • 2020-03-14
                • 2017-09-16
                • 2021-03-21
                • 2019-02-23
                • 1970-01-01
                • 2019-08-20
                • 2017-05-16
                相关资源
                最近更新 更多