我很困惑。
我有一个工作流程,有人可以开始填写产品表单。这是一个很长的格式,我想在输入时将进度保存到服务器(但要等到填满一点之后再保存)。因此,我们从创建表单的URL开始,在他们键入了一点之后,我们在服务器上发布了POST以创建资源,在请求完成之后,我们将URL更新为具有新ID的编辑路径。 / p>
换句话说,您开始在网址/product
处填写表格,然后在填写了一段时间后,网址移至/product/123
。之后,加载该URL将为您提供表单。
所以基本上我有
<Route path={`/product`} exact component={CreateProduct} />
和
<Route exact={true} path="/product/:productId" render={({
match: {params: {productId}},
location: {state: {data}={}}
}) => (
<EditProduct productId={productId} initialData={data}
)} />
看到那个状态?那是因为我从创建模式切换到编辑模式的方式是这样的
const id = await apiFetch(`/api/product`, data, {method: `POST`})
this.props.history.push({pathname: `/product/${id}`, state: {data} })
在我拥有的<EditProduct>
组件的构造函数中
constructor({productId, initialData}) {
this.super()
this.state = {}
if(initialData)
this.setState({data: initialData})
else
getProduct(productId).then(({data}) => this.setState({data}))
}
这样做,<EditProduct>
组件中的初始数据就被植入<CreateProduct>
组件中,而我不需要从服务器或其他任何东西上重新加载它。
这有效,过渡很顺利,URL更新了,一切都很笨拙。
我现在可以继续编辑<EditProduct>
组件,并且可以正确保存。我可以打开一个新标签到相同的URL,它会加载所有内容,然后我可以继续。发生这种情况的原因是,在这种情况下,initialData
是undefined
,因此它是从服务器加载的。是的!
但是
如果我改为刷新原始标签,事情会变得很奇怪。自保存以来累积的所有更改都将丢失。在调试器中深入研究,我发现问题是从initialData
对象传递的location.state.data
不是空的-它是首次创建产品时的初始对象。
那么它到底来自哪里?我只是做了整页刷新(甚至是没有打开缓存和devtools的“硬”刷新)。该数据不在URL中(实际上,将URL粘贴到同一窗口中的另一个选项卡中的复制不存在此问题)。
我知道的唯一机制可以在刷新之间保留数据,但不能持久保存到这样的新选项卡上,sessionStorage
是这样,但是当我在控制台中检查它时,会被告知
> sessionStorage
< Storage {length: 0}
我什至认为,也许React Router会在页面卸载之前和页面加载之后操纵会话存储,但是在我的JavaScript包的第一行中断显示的是完全相同的东西。
那么这种持久性到底是怎么发生的呢??
答案 0 :(得分:0)
我有一个非常相似的问题,同样的困惑。
用window.history.replaceState()
解决了我有一个简单的搜索表单,该表单重定向到第二页,并使用路由器的位置状态重新填充第二页上的搜索输入。
在这种情况下,发生了这种情况:
我通过这样做来解决此问题,以便每次用户在第二页上进行搜索时,我使用正确的搜索词替换window.history.replaceState
的状态。这样,刷新将为用户提供预期的搜索。在第二页的每次搜索中都用一个空对象替换状态也可以很好地工作,使用户每次刷新时都得到一个空搜索。
答案 1 :(得分:0)
我相信提问者已经解决了这个问题,尽管答案已隐藏在评论中。
问题实际上出在这里:
用户重新加载页面时state
来自哪里? state
指的是props.location.state
提供的react-router
TLDR; state
不是普通的javascript实现,它绑定到浏览器环境。
BroswerRouter
的{{1}}直接使用基础的本机浏览历史记录API,因此历史记录API已绑定到平台,您无法根据正常规则预测其行为。
这是特殊的部分:
状态对象可以是任何可以序列化的对象。由于Firefox将状态对象保存到用户的磁盘上,因此可以在用户重新启动浏览器后将其还原
大多数用户将react-router
视为普通的javascript,因此存在问题