Create a broadcaster component
Problems to be solved:
- Make sure the format of the passed props parameter is correct
- Manipulate the DOM elements created by React in React
- Operation of setInterval function during component state switching to ensure no error is reported
Problem solving
The props parameter uses the prop types package to set the parameter format and the default props setting, so as to ensure the correctness of props.
Use the ref attribute provided by react to manipulate the dom element attributes created by react
Calling setInterval and clearing setInterval function in different hook functions
componentDidMount() { this.scoll(); // Execute the core function, run the carousel, and assign setInterval to this.timer } // Solve the problem of component state change setInterval function error componentWillReceiceProps(){ clearInterval(this.timer); //Clear timer in previous carousel function setTimeout(()=>{ this.scroll(); // Re execute the carousel function },0); }
Although this method can achieve the effect, it will report an error when the component is destroyed and rebuilt. The improvement methods are as follows:
componentWillReceiveProps(){ if(this.timer !== undefined){ setTimeout(() => { clearInterval(this.timer); // Unload timing function this.scoll(); },0); }else{ this.scoll(); } }
The actual code is as follows
import React, {Component} from 'react'; import {Link} from 'react-router-dom'; import PropTypes from 'proptypes'; import Style from './Banner.module.css'; const defaultProps = { lists: [] }; class Banner extends Component{ scoll = () => { var i = 0; var j = 0; var num = this.props.lists.length; if(num > 1){ this.refs.banner.style.width = (num+1)*100+'vw'; let btns = document.getElementById('bannerBtn') .querySelectorAll('li'); this.timer = setInterval(function () { if(i>num){ this.refs.banner.style.transition = 'all 0s ease'; i=0; }else{ this.refs.banner.style.transition = 'all 1s ease'; } this.refs.banner.style.left = -i*100+'vw'; if((j > num-1) || (i === num) || (i===0)){ j=0; } btns.forEach((btn,index)=>{ if(index === j){ btn.style.background = '#fafafa'; }else{ btn.style.background = 'transparent'; } }); i++; j++; }.bind(this),2000); } }; componentDidMount() { // Component rendering finished execution this.scoll(); } componentWillReceiveProps() { // Execute when props changes if(this.timer !== undefined){ setTimeout(() => { clearInterval(this.timer); // Unload timing function this.scoll(); },0); }else{ this.scoll(); } } componentWillUnmount() { // Execute when the component is uninstalled or destroyed clearInterval(this.timer); // Unload timing function } render() { var imgs = this.props.lists.map((list,index)=>{ return ( <Link to={list.url} key={index}> <img src={list.img} alt=''/> </Link> ); }); var first = this.props.lists.length > 1 ? <Link to={this.props.lists[0].url}> <img src={this.props.lists[0].img} alt='' /> </Link> :''; var btns = this.props.lists.map((list,index)=>{ if(index===0){ return <li style={{background: '#fafafa'}} key={index}></li>; }else{ return <li key={index}></li>; } }); return ( <div className={Style.banner} onClick={this.scroll}> <div className={Style.bannerMain} ref="banner"> {imgs} {first} </div> <div className={Style.btn}> <ul id='bannerBtn'> {btns} </ul> </div> </div> ); } } Banner.defaultProps = defaultProps; Banner.propTypes = { lists: PropTypes.array }; export default Banner;
No joy, no spray.