我使用redux-sessionstorage将应用程序状态的子集存储到会话存储中。该状态的一部分表示UI中的某些面板是展开还是折叠(可见或隐藏)。
我有一个示例应用程序正好复制了此内容:https://github.com/shawninder/sessionstorage-bug
有关完整的复制步骤,请参见自述文件。
还在线托管了here(请稍等一下以解冻)
重新加载页面时会发生问题。 redux-sessionstorage可以从sessionstorage正确还原以前的状态并触发渲染,但是我用于隐藏和显示的style属性没有更新。
换句话说,这可以按预期工作:
<p>showNotice: {props.app.showNotice ? 'true' : 'false'}</p>
我可以在页面加载中看到showNotice: false
,但是当redux-sessionstorage恢复保存状态时,它立即被showNotice: true
取代。
但是以下操作无效:
<div
className='notice'
style={{
opacity: props.app.showNotice ? 1 : 0,
transform: props.app.showNotice ? 'translateX(0)' : 'translateX(-100%)'
}}
>
Notice!
</div>
该页面加载了隐藏的通知(如预期的那样),但是当redux-sessionstorage恢复状态时不会显示该页面。实际上,它直到我单击两次切换按钮时才显示,这是第一次将showNotice
设置回false
,然后第二次将其设置为true
并显示<div>
。
为什么redux-sessionstorage在这里不更新style
属性,人们通常如何处理呢?
答案 0 :(得分:0)
@lecstor指出了与此问题相关的话题。
这是服务器端渲染(SSR)的事情。 comment上描述的解决方法Dan Abramov解决了该问题。
您正在将Next.js用于SSR。在dev
模式下运行项目时,按Toggle到true并重新加载后,您会在Chrome控制台上看到以下错误消息:
Warning: Text content did not match. Server: "false" Client: "true"
由于Next对客户端的保存状态一无所知,因此它总是将app.showNotice
返回到false
。您还可以在Chrome的“网络”标签上查看GET localhost
返回的内容。
显然,Next.js
试图合并服务器返回的内容和本地呈现的内容,但是无法合并样式。显然,这是Next和React 16 SSR上的预期行为,您可以通过触发第二个render()
或执行以下实现来克服。
class App extends Component {
constructor(props) {
super(props);
this.state = { showNotice: false };
}
componentDidMount() {
this.setState({ showNotice: this.props.app.showNotice });
}
componentWillReceiveProps(props) {
this.setState({ showNotice: props.app.showNotice });
}
render() {
return (
<div>
<p>showNotice: {this.state.showNotice ? 'true' : 'false'}</p>
<button onClick={(event) => {
this.props.dispatch({ type: 'App:toggleNotice' })
}}>toggle</button>
<div
className='notice'
style={{
opacity: this.state.showNotice ? 1 : 0,
transform: this.state.showNotice ? 'translateX(0)' : 'translateX(-100%)'
}}
>
Notice!
</div>
<style jsx>{`
.notice {
width: 100px;
transition-property: opacity, transform;
transition-duration: 0.4s;
}
`}</style>
</div>
)
}
}