【发布时间】:2019-07-13 09:56:33
【问题描述】:
我在 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>
)
}
}
任何提示都会很棒, 谢谢
【问题讨论】:
-
你能提供你的代码吗?
-
如果没有MCVE 或者至少还有一些代码,就不可能说。您可能在
render或某些事件处理程序中调用setState -
这样的查询需要代码审查。请花一些时间分享代码,以便社区更好地接收和快速解决方案
-
好的,我已经提供了我的代码
-
如果需要根据更新后的 props/state 计算 nextState,请使用getderivedstatefromprops。或者 componentWillRecieveProps/componentDidUpdate 如果你使用的是旧版 React。
标签: javascript reactjs state