簡體   English   中英

我如何從渲染 function 內部進行 setState

[英]How can I setState from inside a render function in react

我知道你應該保持渲染函數純凈,但我有一個特殊情況,我需要傳遞一些值並更新渲染 function 內的 state 但我收到以下錯誤消息:

在現有 state 過渡期間無法更新(例如在render中)。 渲染方法應該是純 function 的 props 和 state

代碼:

import Carousel from 'react-elastic-carousel';
import top from '../images/top.png';
import ArrowRight from '../images/arrowRight.svg';
import React, {Component} from 'react';
class contentSlider extends Component {

  state = {
    disabled: '',
    leftArrow: false,
    rightArrow: true
  }

  sliderData = [
    {
      title: 'POLO',
      typeOfcontent: 'Mens T-Shirt',
      rrp: '£105',
      ourPrice: '£55',
      salePrice: '£45',
      image: top
    },
    {
      title: 'POLO',
      typeOfcontent: 'Mens T-Shirt',
      rrp: '£105',
      ourPrice: '£55',
      salePrice: '£45',
      image: top
    },
    {
      title: 'POLO',
      typeOfcontent: 'Mens T-Shirt',
      rrp: '£105',
      ourPrice: '£55',
      salePrice: '£45',
      image: top
    },
    {
      title: 'POLO',
      typeOfcontent: 'Mens T-Shirt',
      rrp: '£105',
      ourPrice: '£55',
      salePrice: '£45',
      image: top
    },
    {
      title: 'POLO',
      typeOfcontent: 'Mens T-Shirt',
      rrp: '£105',
      ourPrice: '£55',
      salePrice: '£45',
      image: top
    },
    {
      title: 'POLO',
      typeOfcontent: 'Mens T-Shirt',
      rrp: '£105',
      ourPrice: '£55',
      salePrice: '£45',
      image: top
    },
    {
      title: 'POLO',
      typeOfcontent: 'Mens T-Shirt',
      rrp: '£105',
      ourPrice: '£55',
      salePrice: '£45',
      image: top
    }

  ]

  breakPoints = [
    { width: 2, itemsToShow: 2, itemsToScroll: 2 },
    { width: 550, itemsToShow: 3, itemsToScroll: 3},
    { width: 850, itemsToShow: 4, itemsToScroll: 3 },
    { width: 970, itemsToShow: 4, itemsToScroll: 3 },
    { width: 1150, itemsToShow: 5, itemsToScroll: 3 },
  ] 

  setDirection = (slideDirection) => {
    switch(slideDirection) {
      case "next":
        this.carousel.slideNext();
        let slideNext = document.getElementById('slider-move');
        
        if(slideNext.classList.contains('test-right')) {
          slideNext.classList.remove('test-right');
          slideNext.classList.add('test-left');
        }
            
      break;
      case "previous":
        this.carousel.slidePrev();
        let slidePrevious = document.getElementById('slider-move');
        
        if(slidePrevious.classList.contains('test-left')) {
          slidePrevious.classList.remove('test-left');
          slidePrevious.classList.add('test-right');
        }

      break;
    }
  }

  getAmountOfPages = (pages, activePage ) => {
  console.log(activePage)

  let firstItem = pages[0];
  let [lastItem] = pages.slice(-1);

  if(firstItem === activePage) {
    this.setState({
      leftArrow: false,
      rightArrow: true,
    })
  } else if(lastItem === activePage) {
    this.setState({
      leftArrow: true,
      rightArrow: false,
    })
  } else {
    this.setState({
      leftArrow: true,
      rightArrow: false,
    })
  }

// get first item in the array and compare it to the active page

// get the last element in the array and compare it to the active page
  }

  render() {
    return (
      <div className="content-slider-wrapper">
        <div className="content-slider-title">
          <span>PRODUCTS OF THE WEEK</span>
        </div>
        <div className={`${this.sliderData.length === 5 ? 'd-xl-none' : ''} arrow-container`}>
          <img onClick={() => this.setDirection("previous")} className="arrow-left" src={ArrowRight} />
          <img onClick={() => this.setDirection("next")} src={ArrowRight} />   
        </div>

        <div className={`${this.sliderData.length === 5 ? 'mt-xl-5' : ''} content-slider-container`}> 
        <div className="test-right" id="slider-move">
          
          
          <Carousel 
              ref={ref => (this.carousel = ref)}
              breakPoints={this.breakPoints} 
              disableArrowsOnEnd={true}
              renderPagination={({ pages, activePage, onClick }) => {
                this.getAmountOfPages(pages, activePage);
                return (
                  <div className={`${this.sliderData.length === 5 ? 'd-xl-none' : ''} black-slider-container`}>
                    {pages.map(page => {
                      const isActivePage = activePage === page
                      return (
                        <div className={isActivePage ? 'black-slider' : 'blank-slider'}
                          key={page}
                          onClick={() => onClick(page)}
                          active={isActivePage}
                        />
                      )
                    })}
                  </div>
                )
              }}
              >
              {this.sliderData.map((item, index) => (
                <div key={index} className="carousel-item-container">
                  <div className="carousel-image-container">
                    <img src={top} />
                  </div>
                  <div className="carousel-text-container">
                    <ul>
                      <li className="carousel-text-container-title">{item.title}</li>
                      <li className="carousel-text-container-text">{item.typeOfProduct}</li>
                      <li className="carousel-text-container-text line-through">RRP {item.rrp}</li>
                      <li className="carousel-text-container-text line-through">Our Price: {item.ourPrice}</li>
                      <li className="carousel-text-container-text">Sale Price: {item.salePrice}</li>
                    </ul>
                  </div>
                </div>
              ))}
            </Carousel>
          </div>
          </div>
      </div>
    )
  }
}

export default contentSlider;

我需要調用這個 function

this.getAmountOfPages(pages, activePage);

這是在我的渲染中,以在需要時更新 state 但是它沒有任何想法......

我是巴西人,因此我會說葡萄牙語,但我會使用翻譯來幫助您。

通過以您嘗試這樣做的方式調用此 function,您將陷入無限循環。 看:

  1. 您在 render() 方法中更新 state;
  2. 由於 state 更新,調用了 render() 方法;
  3. render方法更新state;
  4. 重新來過

我已經使用過這個庫,所以我將向您展示我是如何做到的:

      <Carousel
          itemsToShow={7}
          renderArrow={renderArrow}
          enableMouseSwipe={false}
          pagination={false}
          breakPoints={[
            {
              width: 450,
              itemsToShow: 3,
              enableSwipe: true,
              enableMouseSwipe: true,
              itemsToScroll: 3,
              renderArrow: () => <div />,
            },
            {
              width: 500,
              itemsToShow: 3,
            },
            { width: 620, itemsToShow: 4 },
            { width: 720, itemsToShow: 5 },
            { width: 850, itemsToShow: 6 },
            { width: 1150, itemsToShow: 7 },
          ]}
        >
          {products &&
            products.map((p) => (
              <div key={p.docId} className="products-prod">
                <img
                  onClick={() => addProductCart(p)}
                  alt={p.descricao}
                  src={`data:image/png;base64,${p.thumbnail}`}
                  className={`shadow2 ${
                    !cart.includes(p.docId) && adding.includes(p.docId)
                      ? `pulse`
                      : ``
                  }`}
                />
                <section onClick={() => addProductCart(p)}>
                  {cart.includes(p.docId) ? (
                    <img src={ICONS.shoppingFilled} />
                  ) : (
                    <img src={ICONS.shoppingOutlined} />
                  )}
                </section>
                <article>
                  <h5>R$</h5>
                  {p.preco && formatCash(p.preco, true)}
                </article>
              </div>
            ))}
        </Carousel>

和:

  const renderArrow = ({ onClick, type, isEdge: noMoreItems }) => (
    <Button
      onClick={onClick}
      style={{
        margin: "auto 0",
        borderRadius: "100px",
        background: COLORS.primary,
        borderColor: COLORS.primary,
        width: "30px",
        minWidth: "30px",
        height: "30px",
        minHeight: "30px",
        padding: 0,
        display: "flex",
        justifyContent: "center",
        alignItems: "center",
      }}
      type="primary"
    >
      {type === consts.PREV ? (
        <CaretLeftOutlined style={{ margin: "2px 2px 0 0" }} />
      ) : (
        <CaretRightOutlined style={{ margin: "2px 0 0 2px" }} />
      )}
    </Button>
  );

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM