简体   繁体   English

为什么React-Transition-Group在路由更改时不调用componentWillEnter或componentWillLeave?

[英]Why is react-transition-group not calling componentWillEnter nor componentWillLeave on route change?

I am following this hackernoon guide https://hackernoon.com/animated-page-transitions-with-react-router-4-reacttransitiongroup-and-animated-1ca17bd97a1a in order to apply enter and leave animations to my react components when a route changes. 我正在遵循此hackernoon指南https://hackernoon.com/animated-page-transitions-with-react-router-4-reacttransitiongroup-and-animated-1ca17bd97a1a ,以便在进入路线时将Enter动画留给我的react组件变化。 I have obviously adapted the code to fit my site, and have decided not to use Animated but rather just pure CSS. 我显然已经修改了代码以适合我的网站,并决定不使用Animated而是仅使用纯CSS。 Right now I'm just testing the code with console.log statements, and I noticed that componentWillEnter and componentWillLeave are not being called on route changes. 现在,我只是使用console.log语句测试代码,并且我注意到在路由更改时未调用componentWillEnter和componentWillLeave。 Also, componentWillAppear only gets called once. 此外,componentWillAppear仅被调用一次。

Here is the relevant code for each component, including App.js and index.js: 以下是每个组件的相关代码,包括App.js和index.js:

Animated Wrapper: 动画包装器:

import React, {Component} from "react";
import styles from '../styles/AnimatedWrapper.css';

const AnimatedWrapper = WrappedComponent =>
  class AnimatedWrapper extends Component {
    componentWillAppear(cb) {
      console.log('componentWillAppear');
      cb();
    }
    componentWillEnter(cb) {
      console.log('componentWillEnter');
      cb();
    }
    componentWillLeave(cb) {
      console.log('componentWillLeave');
      cb();
    }
    render() {
      return (
        <div id="animated-wrapper" className={styles.animatedPageWrapper}>
          <WrappedComponent {...this.props}/>
        </div>
      );}
    };

export default AnimatedWrapper;

App.js: App.js:

import React, { Component } from 'react';
import { Route, Switch } from 'react-router-dom';
import TransitionGroup from "react-transition-group/TransitionGroup";

import Navbar from "./components/Navbar";
import Footer from "./components/Footer";
import Slider from "./components/Slider";
import ComingSoon from "./components/ComingSoon";

const firstChild = props => {
  const childrenArray = React.Children.toArray(props.children);
  return childrenArray[0] || null;
}

class App extends Component {
  render() {
    return (
      <div className="App">
        <Navbar />
        <Switch>
          <Route
            path="/coming-soon"
            children={({ match, ...rest }) => (
              <TransitionGroup component={firstChild}>
                {match && <ComingSoon {...rest} />}
              </TransitionGroup>
          )}/>
          <Route
             path="/"
             children={({ match, ...rest }) => (
               <TransitionGroup component={firstChild}>
                 {match && <Slider {...rest} />}
               </TransitionGroup>
          )}/>
        </Switch>
        <Footer />
      </div>
    );
  }
}

export default App;

index.js: index.js:

import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
import App from './App';
import './index.css';

ReactDOM.render(
  <BrowserRouter>
     <App />
   </BrowserRouter>,
  document.getElementById('root')
);

Slider.js: Slider.js:

import React, { Component } from 'react';
import _ from 'lodash';

// components
import AnimatedWrapper from './AnimatedWrapper';
import Separator from './Separator';

// styles
import styles from '../styles/Slider.css';

// images
import Apartment from "../../public/images/apartment.jpg";
import Floor from "../../public/images/floor.jpg";
import Furniture from "../../public/images/furniture.jpg";
import Kitchen1 from "../../public/images/kitchen.jpg";
import Kitchen2 from "../../public/images/kitchen-2.jpg";

class SliderComponent extends Component {
  constructor(props) {
    super(props);

    this.state = {
      currentSlide: 0,
      slides: [Apartment, Floor, Furniture, Kitchen1, Kitchen2]
    };
  }

  componentDidMount() {
    this.zoomAnimation();
    this.slideContentAnimation();

    this.sliderInterval = setInterval(() => {
      if (this.state.currentSlide === 4) {
        if (this.refs.slider) {
          this.setState({ currentSlide: 0 });
        }
      } else {
        if (this.refs.slider) {
          this.setState({ currentSlide: this.state.currentSlide + 1 });
        }
      }
    }, 6000);
  }

  componentWillUpdate() {
    const currentContent = document.getElementById(`content-${this.state.currentSlide}`);
    setTimeout(() => {
      currentContent.classList.remove(`${styles.currentContent}`);
    }, 1500);
  }

  componentDidUpdate() {
    this.zoomAnimation();
    this.slideContentAnimation();
  }

  setSlide(number) {
    this.setState({ currentSlide: number });
  }

  zoomAnimation() {
    setTimeout(() => {
      const currentSlide = document.getElementById(`slide-${this.state.currentSlide}`);
      currentSlide.classList.add(`${styles.slideZoom}`);
    }, 500);
  }

  slideContentAnimation() {
    setTimeout(() => {
      const currentContent = document.getElementById(`content-${this.state.currentSlide}`);
      if (currentContent) {
        currentContent.classList.add(`${styles.currentContent}`);
      }
    }, 1500);
  }

  renderSlides() {
    return this.state.slides.map((slide, index) => {
      const isCurrent = index === this.state.currentSlide;

      const slideStyle = {
        backgroundImage: `url(${this.state.slides[index]})`
      }

      return (
        <div
          id={`slide-${index}`}
          key={`slide-${index}`}
          className={`
            ${styles.slide}
            ${isCurrent ? styles.currentSlide : null}
          `}
          style={slideStyle}
          alt="slide">
            <div
              id={`content-${index}`}
              key={`content-${index}`}
              className={`
                ${styles.content}
            `}>
              <h1>{`WE SPECIALIZE IN KITCHENS ${index}`}</h1>
              <Separator
                containerWidth={720}
                circleWidth={5}
                circleHeight={5}
                backgroundColor="#fff"
                lineWidth={350}
                lineColor="#fff"
              />
              <div
                className={`${styles['hvr-sweep-to-top']} ${styles.btn}`}>
                More Information
              </div>
            </div>
        </div>
      );
    });
  }

  renderNavBar() {
    return (
      <div className={styles.sliderNav}>
        {_.range(5).map((index) => {
          return (
            <div
              key={index}
              onClick={() => this.setSlide(index)}
              className={this.state.currentSlide === index ? styles.current : null}>
            </div>
          )
        })}
      </div>
    )
  }

  render() {
    return (
      <div className={styles.container} ref="slider">
        <div className={styles.slidesContainer}>
          {this.renderSlides()}
        </div>

        {this.renderNavBar()}
      </div>
    );
  }
}

const Slider = AnimatedWrapper(SliderComponent);
export default Slider;

ComingSoon.js: ComingSoon.js:

import React from 'react';
import AnimatedWrapper from './AnimatedWrapper';
import styles from '../styles/ComingSoon.css';

const ComingSoonComponent = function() {
  return (
    <div>
      <div className={styles.mainContent}>
        <div>
          <h1 className={styles.mainTitle}>{`Coming Soon`}</h1>
        </div>
      </div>
    </div>
  );
};

const ComingSoon = AnimatedWrapper(ComingSoonComponent);
export default ComingSoon;

Try to Use react-transition-group , it will be help. 尝试使用react-transition-group会有所帮助。

You can use it like this Example . 您可以像本示例一样使用它。 As follow main code: 如以下主要代码:

import { BrowserRouter, Route, Switch, Link } from 'react-router-dom'
import { CSSTransition, TransitionGroup } from 'react-transition-group'

const PageFade = (props) => (
  <CSSTransition 
    {...props}
    classNames="fadeTranslate"
    timeout={1000}
    mountOnEnter={true}
    unmountOnExit={true}
  />
)

const Layout = ({ children }) => (
  <section>
    <nav>
      <ul>
        <li><Link to="/">Home</Link></li>
        <li><Link to="/about">About</Link></li>
        <li><Link to="/topics">Non existing</Link></li>
      </ul>
    </nav>
    <hr />
    {children}
  </section>
)

const App = (props) => {
  const locationKey = props.location.pathname

  return (
  <Layout>
    <TransitionGroup>
      <PageFade key={locationKey}>
        <section className="fix-container">
          <Switch location={props.location}>
            <Route exact path="/" component={Home} />
            <Route exact path="/about" component={About} />
            <Route component={NotFound} />
          </Switch>
        </section>
      </PageFade>
    </TransitionGroup>
  </Layout>
  )
}

const BasicExample = () => (
  <BrowserRouter>
    <Route path="/" component={App} />
  </BrowserRouter>
);

render(<BasicExample />, document.getElementById('root'));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM