我正在尝试弄清楚当用户使用后退/前进浏览器按钮导航时,如何使我的React SPA应用维护状态。例如。用户正在填写表格,然后他前后移动,表格会自动恢复。
我回顾了很多JavaScript路由器,但似乎都没有正确地解决这个问题......(甚至根本没有)。
目前我正在使用React Router 4,这是我采用的模式:
history.replace(this.state)
保存当前页面的状态;然后我使用history.push(newLocation)
componentWillMount
)我检查this.props.location.state !== undefined
如果是,我会使用this.setState(this.props.location.state)
我的问题是:上述模式是否正确?建议?有没有更好,更广泛采用的方式?
答案 0 :(得分:10)
this.setState()
后,我使用window.history.replaceState({ key: history.location.key, state: this.state})
willMount
和willReceiveProps
)时,我检查props.params.location.state
中的状态:如果有,我会恢复它;如果没有,我会创造一个全新的状态。this.setState
和window.history.pushState
这个解决方案似乎很好用,唯一的小缺点是:
this.setState
是一个陷阱,因为它是异步的,你不能在它之后使用this.state
,除非你做了诡计。 constructor()
的{{1}} 总的来说,我写了一个Component
,扩展PageComponent
,完成所有初始/恢复工作;它还会覆盖Component
以使其与历史记录自动同步并避免异步烦恼。
答案 1 :(得分:0)
使用getDerivedStateFromProps
并检查props.location.key
的值是否有更改,以仅在用户使用浏览器按钮导航时恢复状态。
static getDerivedStateFromProps(props,states){
if ((typeof props.location !== 'undefined') &&
(typeof props.location.state !== 'undefined') &&
(states.location_key !== props.location.key)) {
let newState = props.location.state;
newState.location_key = props.location.key;
return newState;
}
}
答案 2 :(得分:-1)
我也考虑过这个问题, 例如,您具有多步骤表单,并且您也想通过浏览器控件在各步骤之间导航。结果,您必须使用路由器来存储activeStep,但是您不想在浏览器URL中共享它。解决方案是将存储步骤设置为路由器状态:
const location = useLocation();
const history = useHistory();
const onSubmit = useCallback(() => {
history.push({
..location,
state: {
activeStep: 1
}
});
}, [...]);
结果,您的步骤将在页面刷新后恢复事件,但是您无法将步骤共享给其他用户。太完美了。
下一个问题是在步骤之间存储表单数据。我们也不能以路由器状态存储它。我为此选择了sessionStorage。它具有类似路由器状态的相似属性。结果,您必须通过提交示例来更新会话存储,并以init形式获取数据:
const location = useLocation();
const history = useHistory();
const [initData] = useState(getFormDataFromStorage());
const onSubmit = useCallback(() => {
saveFormDataToStorage(...);
history.push({
..location,
state: {
activeStep: 1
}
});
}, [...]);