反应组件中的滑块返回'无法读取未定义的属性样式'

时间:2018-04-26 12:01:20

标签: javascript reactjs

我试图为滑块创建一个组件,但由于某种原因它不起作用!

第一次渲染时,我收到以下错误:'无法读取未定义的属性样式...'。

当我尝试记录 x [slideIndex-1] 时,我首先得到未定义的内容,然后在onClick事件侦听器触发后获得正确的值。

此外,当我在点击任何按钮之前记录 x.length 时,我得到0,但在onClick之后,它会切换到4.

这是整个组件文件:

import React from 'react';

export default () => {
  var slideIndex = 1;
    showDivs(slideIndex);

  function plusDivs(n) {
    showDivs(slideIndex += n);
}

  function showDivs(n) {
    var i;
    var x = document.getElementsByClassName("slider__img");
    if (n > x.length) {slideIndex = 1}
    if (n < 1) {slideIndex = x.length}
    for (i = 0; i < x.length; i++) {
       x[i].style.display = "none";
    }
    x[slideIndex-1].style.display="block";
}

  return (
    <div className="content-container">
      <img className="slider__img" src="../images/foo.jpg"/>
      <img className="slider__img" src="../images/foo2.jpg"/>
      <img className="slider__img" src="../images/foo3.jpg"/>
      <img className="slider__img" src="../images/foo4.jpg"/>
      <button onClick={()=>plusDivs(1)}>Next</button>
      <button onClick={()=>plusDivs(-1)}>Previous</button>
    </div>
  )
}

2 个答案:

答案 0 :(得分:0)

在评论中指出。使用React时直接操作DOM元素是不好的做法。 React使用虚拟DOM。为了最小化DOM操作,React首先计算出必须在虚拟DOM中应用的所有更改,然后实际呈现给真实DOM。这就是为什么在使用React时自己操纵DOM元素可以被认为是一种反模式。

解决问题的一种方法如下:

import React, { Component } from 'react';

export class YourComponent extends Component {
  constructor() {
    super();
    this.state = {
      slideIndex: 1,
      images: [
        '../images/foo.jpg',
        '../images/foo2.jpg',
        '../images/foo3.jpg',
        '../images/foo4.jpg'
      ]
    };
  }

  pludDivs(n) {
    const { images } = this.state;
    if (n > images.length) {
      this.setState({ slideIndex: 1 });
    }
    if (n < 1) {
      this.setState({ slideIndex: images.length - 1 });      
    }
  }

  render() {
    const { images, sliderIndex } = this.state;
    return (
      <div className="content-container">
        <img className="slider__img" src={images[slideIndex]} />
        <button onClick={() => plusDivs(1)}>Next</button>
        <button onClick={() => plusDivs(-1)}>Previous</button>
      </div>
    );
  }
}

希望这有帮助!如果您有任何问题,请与我们联系。

答案 1 :(得分:0)

这段代码看起来不太干净,可能有改进的潜力,但它有效!谢谢大家指出我关于DOM和虚拟DOM的正确方向!

import React from 'react';

export default class Slider extends React.Component {
  constructor() {
    super();
    this.state = {
      slideIndex: 0,
      images: [
        '../images/foo1.jpg',
        '../images/foo2.jpg',
        '../images/foo3.jpg',
        '../images/foo4.jpg'
      ]
    };
  }

  plusDivs(n) {
    const { images, slideIndex } = this.state;
    if(n<0){
      if(slideIndex>0){
        this.setState((prevState)=>({
          slideIndex : prevState.slideIndex - 1
        }));
      } else {
        this.setState(()=>({
          slideIndex:images.length-1
        }))
      }

    }
    if(n>0){
      if(slideIndex<images.length-1){
        this.setState((prevState)=>({
          slideIndex : prevState.slideIndex +1
        }))
      } else {
        this.setState(()=>({
          slideIndex : 0
        }))
      }
    }
  }

  render() {
    const { images, slideIndex } = this.state;
    return (
      <div className="content-container">
        <img className="slider__img" src={images[slideIndex]} />
        <button onClick={() => this.plusDivs(1)}>Next</button>
        <button onClick={() => this.plusDivs(-1)}>Previous</button>
      </div>
    );
  }
}