为什么 redux-sessionstorage 在恢复状态时不更新节点的属性?
Why is redux-sessionstorage not updating my node's attributes when restoring state?
我使用 redux-sessionstorage 将我的应用状态的一个子集存储到会话存储中。该状态的一部分表示 UI 中的某些面板是展开还是折叠(可见或隐藏)。
我有一个示例应用程序完全重现了这个:https://github.com/shawninder/sessionstorage-bug
有关完整的复制步骤,请参阅自述文件。
也在线托管here(稍等片刻解冻)
重新加载页面时出现问题。 redux-sessionstorage 正确地从 sessionstorage 恢复以前的状态并触发渲染,但是我用来隐藏和显示的样式属性没有更新。
换句话说,这按预期工作:
<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
属性,人们通常如何处理这个?
@lecstor 指出了关于此问题的正确线索。
这是服务器端渲染 (SSR) 的问题。 Dan Abramov 在此 comment 上描述的解决方法解决了这个问题。
您正在使用 Next.js 进行 SSR。当 运行 您的项目处于 dev
模式时,您可以在 Chrome 控制台上看到以下错误消息,按下 Toggle to true 并重新加载后:
Warning: Text content did not match. Server: "false" Client: "true"
由于 Next 对客户端保存的状态一无所知,它总是 returns 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>
)
}
}
我使用 redux-sessionstorage 将我的应用状态的一个子集存储到会话存储中。该状态的一部分表示 UI 中的某些面板是展开还是折叠(可见或隐藏)。
我有一个示例应用程序完全重现了这个:https://github.com/shawninder/sessionstorage-bug
有关完整的复制步骤,请参阅自述文件。
也在线托管here(稍等片刻解冻)
重新加载页面时出现问题。 redux-sessionstorage 正确地从 sessionstorage 恢复以前的状态并触发渲染,但是我用来隐藏和显示的样式属性没有更新。
换句话说,这按预期工作:
<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
属性,人们通常如何处理这个?
@lecstor 指出了关于此问题的正确线索。
这是服务器端渲染 (SSR) 的问题。 Dan Abramov 在此 comment 上描述的解决方法解决了这个问题。
您正在使用 Next.js 进行 SSR。当 运行 您的项目处于 dev
模式时,您可以在 Chrome 控制台上看到以下错误消息,按下 Toggle to true 并重新加载后:
Warning: Text content did not match. Server: "false" Client: "true"
由于 Next 对客户端保存的状态一无所知,它总是 returns 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>
)
}
}