[英]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:
看:
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.