Почему «веб-страница замедляется» при использовании цикла while с setTimeout в React? - PullRequest
0 голосов
/ 21 мая 2018

Я сделал этот компонент в React с циклом while, в котором есть setTimeout.Это приводит к тому, что браузер перестает отвечать на запросы, и я получаю «замедление веб-страницы» в браузере разработчиков Firefox и в Chrome тоже.Какова возможная причина?Вот код: -

class Adbanner extends React.Component{

changer() {

        var i=0;  
        while(i>=0 && i<4){ 
          setTimeout(function(){
             document.getElementById('ad').src=adarray[i];
             i++; 
          }, 2000);            

        }     
}

    render() {
    return (
       <div>
            <input id="ad" type="image" src={ad2} style={{position:'absolute',height:'50%',width:'100%'}}></input>      
          {setInterval(this.changer, 2000)}  
       </div>
    );
  }
}

export default Adbanner;

Как это решить?

Ответы [ 4 ]

0 голосов
/ 21 мая 2018

while повторяется до тех пор, пока i не будет повторен 4 раза.Теперь i повторяется, когда setTimeout выполняет данную ему функцию, НО эта функция выполняется только через 2 секунды.Между тем, while зацикливается миллионы раз.

Хотя вы не используете силу React!Посмотрите это руководство на веб-сайте React, которое научит вас, как выполнить этот точный сценарий: https://reactjs.org/docs/state-and-lifecycle.html

например,

class Adbanner extends React.Component {

  // Set this component's state as the current ad index
  state = {ad: 0};

  // Rotates the ad index state every 2 seconds
  rotateAd () {
    this.setState({ad: (this.state.ad + 1) % adarray.length});
    this.timer = setTimeout(this.rotateAd, 2000);
  }

  // Start rotating the ad index when mounted
  componentDidMount () {
    this.rotateAd();
  }

  // Renders when constructed, then whenever the state changes (or when React wants to)
  render() {
    return (
      <div>
        <input id="ad" type="image" src={adarray[this.state.ad]} style="position:absolute, height:50%, width:100%">
      </div>
    );
  }

  // Stop the update timer when unmounting
  componentWillUnmount () {
    clearTimeout(this.timer);
  }
}

export default Adbanner;

Я не проверял это.Дайте мне знать, как это работает.

0 голосов
/ 21 мая 2018

Вы не хотите вызывать setInterval внутри вашей функции рендеринга.Рендер должен быть свободен от побочных эффектов.Происходит то, что каждый раз, когда компонент или его родительские изменения, рендеринг вызывается.Это означает, что ваш интервал создается, возможно, много раз.

Вместо этого переместите setInterval в componentDidMount()

Кроме того, в вашем setInterval вы создаете 4 вызова setTimeout.Таким образом, каждые 2 секунды вы будете обновлять таблицу ad 4 раза.Похоже, это не совсем то, что вы хотите.

0 голосов
/ 21 мая 2018

В этом коде есть несколько проблем:

  1. document.getElementById не является допустимым способом изменения атрибутов в React.

  2. Вы выполняете setInterval в методе рендеринга.Теперь представьте, что происходит: первый раз рендер называется setInterval , а затем вызывается четыре метода setTimeout .При выполнении первого тайм-аута снова вызывается render, который в конечном итоге запускает новый setInterval .Это приводит к бесконечному циклу setInterval и рендеринга .

Вы должны использовать метод фазы жизненного цикла фиксации дляметод setinterval, такой как componentDidMount , так что setInterval вызывается только один раз.

0 голосов
/ 21 мая 2018
var i=0;  
while(i>=0 && i<4){ 
  setTimeout(function(){
  document.getElementById('ad').src=adarray[i];
  i++; 
}, 2000);
}       

setTimeout не ожидает завершения.setTimeout отправляет функцию в другую структуру данных и продолжает проходить через код.Он просто продолжает циклически повторяться настолько быстро, насколько возможно в вычислительном отношении.Попробуйте сделать это:

var i=0;  
while(i>=0 && i<4){ 
  setTimeout(function(){
  document.getElementById('ad').src=adarray[i];
  i++; 
}, 2000);
console.log('created a setTimeout')
}    

Похоже, вы пытаетесь запустить функцию 4 раза, ожидая 2000 мс при каждом запуске.setInterval с условием clearInterval идеально подойдет для ваших нужд

function changer() {
  var i=0;  
  let imageChange = setInterval(() => {
    if (i < 4) {
      document.getElementById('ad').src=adarray[i];
      i++
    } else {
      clearInterval(imageChange)
    }
  }, 2000)
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...