gpt4 book ai didi

javascript - 我的 ReactJS 组件怎么可能在旧状态和新状态之间交替?

转载 作者:行者123 更新时间:2023-11-30 14:09:15 26 4
gpt4 key购买 nike

我在 render() 函数中放置了一个 console.log。

我在函数内部使用 setState()。然后我的组件更新,但紧接着我可以检查状态是否恢复到旧状态。

编辑:现在我的问题是在扩展时正确显示状态,我认为其余的工作正常。

这是我的沙盒: https://codesandbox.io/s/77ymmnpr1

在我的代码中,我创建了三个可扩展的标签,然后我放置了一些 labelComponent 来覆盖它们。叠加层有一个按钮可以返回菜单。问题是,当我随后展开另一个 labelComponent 时,旧状态与显示新状态之间存在轻微的滞后。因此,我向您提供了 console.log。

在控制台中放置如下内容:

PATHNAME: newState
PATHNAME: oldState
PATHNAME: newState
PATHNAME: oldState

编辑:现在我的控制台在第二次渲染时返回:

stateOne

currentState

然后,在第三次渲染时:

stateOne

stateTwo

currentState

第四次渲染:

stateOne

stateTwo

stateThree

currentState

这是什么意思?我调用 this.setState() 只是为了将新状态放入其中,那么为什么它又回到旧状态呢?

这是我的 react.js 代码:

export default class Label extends Component {

state={
labelStock:[],

sequence:undefined,
labelToRemove:[],
pathname:"",
displayLabel:false,

displayFreshFood:false,
displayLocalFarm:false,
displayBeerQuality:false
}

componentDidMount(){
this.setLabelArray()
}

shouldComponentUpdate(nextProps, nextState) {
let {pathname}= nextState
console.log("NEXTSTATE: ", pathname)
if(this.state.pathname !== nextState.pathname){
if((
pathname.includes("freshfood") ||
pathname.includes("localfarm") ||
pathname.includes("beerquality") ) && this.state.labelToRemove.length >0
){
this.setState({displayLabel:true})
}
else if(this.state.displayLabel !== nextState.displayLabel){
this.setState({displayLabel:false})
}

return true
}
else if(this.state.displayLabel !== nextState.displayLabel){
return true
}

return false
}
setLabelArray=()=>{
let labelArray=[]

labelStock.forEach(function (item) {
labelArray.push(item.name);
});

this.setState({labelStock:labelArray})
}

renderLabel=()=>(
labelStock.map((item, index) =>{

return (
<div
ref={item.name}
key={index}
style={{backgroundImage: `url(${item.image})`}}
className={this.state.labelToRemove.includes(item.name) ? `${style.label_container} ${style.label_to_remove}` : style.label_container}
>
<div
style={{display: this.state.displayLabel ? 'none' : 'initial' }}
onClick={() => this.expand(item.name)}
className={style.more_info_button}>
<img src={moreInfoButton} alt=""/>
</div>
<div id={style.label_item} > Here some text</div>
</div>
)
})
)

expand=(item)=>{

console.log("IN EXPAND")
let removeItem= this.state.labelStock.filter(word => word!== item);
this.setState({
labelToRemove:removeItem,
displayLabel:true,
pathname:""
})
let [removeOne, removeTwo]= removeItem
let removeOneStyle=this.refs[removeOne].style;
let removeTwoStyle=this.refs[removeTwo].style;

removeOneStyle.opacity="0";
removeTwoStyle.opacity="0";
removeOneStyle.top="-20%";
removeTwoStyle.top="-20%";

setTimeout(function(){
removeOneStyle.width="0vw";
removeTwoStyle.width="0vw";

}, 750);

removeOneStyle.visibility="hidden";
removeTwoStyle.visibility="hidden";

let itemStyle= this.refs[item].style
let layoutStyle=this.refs.layout.style
layoutStyle.padding="0";
layoutStyle.gridColumnGap="0";


this.refs[item].addEventListener('transitionend', (e)=> {
// let label= item.toLowerCase()
// this.setState({pathname:label})
if(e.propertyName !=="width") return
setTimeout(() => {
let updatedPathname= "label/" + item.toLowerCase();
let label= item.toLowerCase()
if(e.propertyName ==="width") this.setState({pathname:label})
}, 1000);
}); item

itemStyle.height= 100+"vh";
itemStyle.width= 100+"vw";
itemStyle.zIndex="100";
}


menuBack=()=>{
this.setState({
displayLabel:false,
labelToRemove:""
})

let item = this.state.pathname

let enterItem= this.state.labelStock.filter(word => word!== item);
// this.setState({

// })
let [enterOne, enterTwo]= enterItem
// console.log("removeOne, removeTwo: ", removeOne, removeTwo)
let enterOneStyle=this.refs[enterOne].style;
let enterTwoStyle=this.refs[enterTwo].style;

enterOneStyle.opacity="1";
enterTwoStyle.opacity="1";

enterOneStyle.top="0%";
enterTwoStyle.top="0%";

setTimeout(function(){
enterOneStyle.width="25vw";
enterTwoStyle.width="25vw";

}, 750);

enterOneStyle.visibility="visible";
enterTwoStyle.visibility="visible";

let itemStyle= this.refs[item].style
let layoutStyle=this.refs.layout.style
layoutStyle.padding="0 1vw";
layoutStyle.gridColumnGap="1.5vw";

itemStyle.height= "50vh";
itemStyle.width= "25vw";
itemStyle.zIndex="10";
this.setState({pathname:""})
}

render() {
var hiddenStyle={ visiblity:"hidden"};
var displayStyle={display:"inline-block"};
var displayFreshFood = this.state.pathname.includes("freshfood") && this.state.displayLabel
var displayBeerQuality = this.state.pathname.includes("beerquality") && this.state.displayLabel
var displayLocalFarm= this.state.pathname.includes("localfarm") && this.state.displayLabel

console.log("PATHNAME: "+ this.state.pathname)
return (
<div
className={style.page}
>

<div
ref="freshfood"
className={style.label_content}
style={{display: this.state.pathname.includes("freshfood") && this.state.displayLabel ? 'block' : 'none' }}
>
<FreshFood/>
</div>

<div
ref="localfarm"
className={style.label_content}
style={{display: this.state.pathname.includes("localfarm") && this.state.displayLabel ? 'block' : 'none' }}
>
<LocalFarm/>
</div>

<div
ref="beerquality"
className={style.label_content}
style={{display: this.state.pathname.includes("beerquality") && this.state.displayLabel ? 'block' : 'none' }}
>
<BeerQuality
style= {this.state.displayBeerQuality?
displayStyle: hiddenStyle}
/>
</div>

<div
className={style.label_background}
style={{opacity: this.state.displayLabel ? 0.5: 1 }}

>
<div
id={style.presentation_video}
>
<video
autoPlay="autolay"
muted
loop
controls
>
<source src={goldLightVideo} type="video/mp4"/>
<source src={goldLightVideo} type="video/ogg"/>
error: video module fails to display
</video>
</div>
<div
ref="layout"
className={style.label_layout}
>
{this.renderLabel()}
</div>
</div>
<BackButton
className={style.back_button}
visible={this.state.displayLabel}
onClick={this.menuBack}
>
<img id={style.back_button_icon} src={backButtonIcon} alt=""/>
</BackButton>
</div>
)


}
}

任何提示都会很棒,谢谢

最佳答案

您正在为 transitionend 事件添加一个事件监听器,它会在超时后设置状态。但是,您永远不会删除该监听器,因此每次您在 DOM 中操作元素转换时都会调用它,这基本上是在每个单击事件上发生的。您可以通过在 transitionend 事件监听器完成它的工作后(即在它设置状态之后)删除它来解决这个问题。以下代码应放在您的扩展函数中,替换您的 this.refs[item].addEventListener(...) 逻辑:

this.addTransitionListener = listener.bind(this);
function listener(e) {
// let label= item.toLowerCase()
// this.setState({pathname:label})
if (e.propertyName !== "width") return
setTimeout(() => {
if (e.propertyName === "width") {
let updatedPathname = "label/" + item.toLowerCase();
let label = item.toLowerCase()
this.setState({
pathname: label,
displayLabel: true
}, () => {
console.log('removing listener')
this.refs[item].removeEventListener('transitionend', this.addTransitionListener)
})
}
}, 1000);
}
this.refs[item].addEventListener('transitionend', this.addTransitionListener);

可以在此处找到带有更改的代码分支:https://codesandbox.io/s/34klvpyw9p

关于javascript - 我的 ReactJS 组件怎么可能在旧状态和新状态之间交替?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54773997/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com