简体   繁体   English

我如何从渲染 function 内部进行 setState

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

i know you are supposed to keep render functions pure but I have a special case where I need to pass some values and update the state inside a render function but i am getting the following error message:我知道你应该保持渲染函数纯净,但我有一个特殊情况,我需要传递一些值并更新渲染 function 内的 state 但我收到以下错误消息:

Cannot update during an existing state transition (such as within render ).在现有 state 过渡期间无法更新(例如在render中)。 Render methods should be a pure function of props and state渲染方法应该是纯 function 的 props 和 state

Code:代码:

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;

I need to call this function我需要调用这个 function

this.getAmountOfPages(pages, activePage); this.getAmountOfPages(pages, activePage);

which is inside my render to update the state when needed however it dont work any ideas....这是在我的渲染中,以在需要时更新 state 但是它没有任何想法......

I am Brazilian and therefore I speak Portuguese, but I will use the translator to try to help you.我是巴西人,因此我会说葡萄牙语,但我会使用翻译来帮助您。

By calling this function the way you are trying to do it, you would fall into an infinite loop.通过以您尝试这样做的方式调用此 function,您将陷入无限循环。 Look:看:

  1. You update the state inside the render () method;您在 render() 方法中更新 state;
  2. The render () method is called due to the state update;由于 state 更新,调用了 render() 方法;
  3. The render method updates the state; render方法更新state;
  4. all over again重新来过

I've already used this library, so I'll show you how I did it:我已经使用过这个库,所以我将向您展示我是如何做到的:

      <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>

And:和:

  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.

相关问题 如何在React中不在render函数中使用setState - How to not use setState inside render function in React 我可以从脚本标签内的外部全局函数中设置反应功能组件的状态吗? - Can i setState of a react functional component from a external gloabal function present inside script tag? 是否可以在反应渲染中创建一个 function 包含一个 if 语句到 setState - Is it possible to create a function inside react render that contains an if statement to setState 如何从 function 返回 React 组件并渲染它 onClick? - How can I return a React Component from a function and render it onClick? 回调内部的setState,以在React组件中呈现相关内容 - setState from inside of a callback to render related content in a React component 如何在反应中进行函数调用之前设置状态? - How can I setstate before making function call in react? 使用React,如何重用setState函数而不是复制和粘贴? - With React, how can I reuse the setState function instead of copying and pasting? 我可以在传递给 useCallback 的函数内部设置状态吗? - Can I setState inside function passed to useCallback? 使用setTimeout的setState时如何重新渲染react-component? - How can I re-render react-component when I setState using setTimeout? React:从渲染函数内部调用一个函数 - React : Call a function from inside render function
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM