使用浏览器 'back' 按钮时 React 中的状态和显示不一致
inconsistent state and display in React when using browser 'back' button
我在 Rails 5.1 应用程序中使用 React 16.1.1(带有 react-rails gem)。
特定页面上的 React 组件工作正常,除非使用浏览器 'back' 按钮返回此页面(使用 firefox / chrome / safari 测试)。在那种情况下,显示与组件的状态不一致。我已经设置了一个问题演示:https://lit-bastion-28654.herokuapp.com/。
重现步骤:
- 在/page1
- 单击 'selection mode' 按钮,它会将 'selectionMode' 设置为 true
- 点击'page 2'
- 使用 'back' 按钮返回第 1 页
- 预期行为:按钮为灰色(组件加载时 selectionMode 重置为 false)。观察到的行为:按钮仍然是蓝色的?!
在那里,你可以看到按钮是蓝色的,好像 selectionMode
是真的,但是反应浏览器插件显示 selectionMode
是假的。 React浏览器插件显示错误信息:显示按钮没有'btn-primary' class(如果selectionMode为false是正常的),但你可以明显看到DOM ,它有 'btn-primary' class,因为它看起来是蓝色的。
这是我的代码:
page1.html.erb:
<%= react_component("EditableCardList", { editable: true }) %>
editable_card_list.js.jsx:
class EditableCardList extends React.Component {
constructor(props) {
super(props);
this.state = {
selectionMode: false
};
this.toggleSelectionMode = this.toggleSelectionMode.bind(this);
}
toggleSelectionMode() {
this.setState(prevState => ({ selectionMode: !prevState.selectionMode }));
}
render() {
if (this.props.editable === true)
return (
<div>
<div className="row card-buttons">
<div className="col-md-12">
<div className="pull-left">
<ManageCardsButtons
selectionMode={this.state.selectionMode}
toggleSelectionMode={this.toggleSelectionMode}
/>
</div>
</div>
</div>
</div>
)
}
}
manage_cards_buttons.js.jsx:
class ManageCardsButtons extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<span>
<button type="button" className={`btn btn-default btn-sm ${this.props.selectionMode ? 'btn-primary' : ''}`} onClick={this.props.toggleSelectionMode}>Selection mode</button>
{ this.props.selectionMode && <span>selection mode</span> }
</span>
)
}
}
所以我的问题是:如何确保在浏览器中使用 'back' 后,按钮正确重新呈现(并且显示为灰色而不是蓝色)?
这个问题可能与 turbolinks 和缓存有关,但我还没有弄清楚。
当您返回 page1 时,组件重新呈现,并设置默认的 selectionMode,在您的情况下为 false。
- 你可以使用 redux。
- 您可以将 selectionMode 保存到您的
localStorage 当它改变时,默认情况下从
存储空间。
React 和 TurboLinks 冲突,所以我的最终解决方案是在该特定页面上禁用 TurboLinks 缓存。
我在 Rails 5.1 应用程序中使用 React 16.1.1(带有 react-rails gem)。
特定页面上的 React 组件工作正常,除非使用浏览器 'back' 按钮返回此页面(使用 firefox / chrome / safari 测试)。在那种情况下,显示与组件的状态不一致。我已经设置了一个问题演示:https://lit-bastion-28654.herokuapp.com/。
重现步骤:
- 在/page1
- 单击 'selection mode' 按钮,它会将 'selectionMode' 设置为 true
- 点击'page 2'
- 使用 'back' 按钮返回第 1 页
- 预期行为:按钮为灰色(组件加载时 selectionMode 重置为 false)。观察到的行为:按钮仍然是蓝色的?!
在那里,你可以看到按钮是蓝色的,好像 selectionMode
是真的,但是反应浏览器插件显示 selectionMode
是假的。 React浏览器插件显示错误信息:显示按钮没有'btn-primary' class(如果selectionMode为false是正常的),但你可以明显看到DOM ,它有 'btn-primary' class,因为它看起来是蓝色的。
这是我的代码:
page1.html.erb:
<%= react_component("EditableCardList", { editable: true }) %>
editable_card_list.js.jsx:
class EditableCardList extends React.Component {
constructor(props) {
super(props);
this.state = {
selectionMode: false
};
this.toggleSelectionMode = this.toggleSelectionMode.bind(this);
}
toggleSelectionMode() {
this.setState(prevState => ({ selectionMode: !prevState.selectionMode }));
}
render() {
if (this.props.editable === true)
return (
<div>
<div className="row card-buttons">
<div className="col-md-12">
<div className="pull-left">
<ManageCardsButtons
selectionMode={this.state.selectionMode}
toggleSelectionMode={this.toggleSelectionMode}
/>
</div>
</div>
</div>
</div>
)
}
}
manage_cards_buttons.js.jsx:
class ManageCardsButtons extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<span>
<button type="button" className={`btn btn-default btn-sm ${this.props.selectionMode ? 'btn-primary' : ''}`} onClick={this.props.toggleSelectionMode}>Selection mode</button>
{ this.props.selectionMode && <span>selection mode</span> }
</span>
)
}
}
所以我的问题是:如何确保在浏览器中使用 'back' 后,按钮正确重新呈现(并且显示为灰色而不是蓝色)?
这个问题可能与 turbolinks 和缓存有关,但我还没有弄清楚。
当您返回 page1 时,组件重新呈现,并设置默认的 selectionMode,在您的情况下为 false。
- 你可以使用 redux。
- 您可以将 selectionMode 保存到您的 localStorage 当它改变时,默认情况下从 存储空间。
React 和 TurboLinks 冲突,所以我的最终解决方案是在该特定页面上禁用 TurboLinks 缓存。