【发布时间】:2018-12-22 07:35:26
【问题描述】:
我真的很困惑。
我有一个工作流程,有人可以开始为产品填写表格。这是一个很长的表格,我想在他们输入时将进度保存到服务器(但直到他们填写一下)。因此,我们从创建表单的 url 开始,在他们输入一段时间后,我们 POST 以在服务器上创建资源,在请求完成后,我们将 url 更新为具有新 id 的编辑路由。
换句话说,您开始在 url /product 处填写表单,然后在您填写了一段时间后,该 url 将转移到 /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> 组件中播种的,我不需要从服务器或其他任何地方重新加载它。
这行得通,过渡顺利,网址更新,一切都很好。
我现在可以继续编辑<EditProduct> 组件并正确保存。我可以打开一个新选项卡到相同的 url,它会加载所有内容,我可以继续。发生这种情况是因为在那种情况下initialData 是undefined,所以它是从服务器加载的。耶!
但是
如果我改为刷新原始标签,事情会变得很奇怪。自保存以来累积的任何更改都将丢失。在调试器中向下钻取,我发现问题是从 location.state.data 对象传递的 initialData 不是空的 - 它是首次创建产品时的初始对象。
那么它到底是从哪里来的呢?我刚刚进行了整页刷新(甚至是没有缓存和开发工具打开的“硬”刷新)。该数据不在 URL 中(实际上,将 url 复制粘贴到同一窗口中的另一个选项卡中没有这个问题)。
我知道的唯一机制可以在刷新期间保留数据,但不能保存到像这样的新标签页是 sessionStorage,但是当我在控制台中检查它时,我被告知
> sessionStorage
< Storage {length: 0}
我什至认为 react-router 可能在页面卸载之前和加载之后操纵会话存储,但是在我的 javascript 包的第一行中断显示完全相同的事情。
那么这种持久性到底是怎么发生的!?
【问题讨论】:
-
history.state -
@azium 是的...我看到一些对它的引用,但没有任何真实信息...听起来可能是...在当前浏览器会话中存储内容?但是不是使用
sessionStorage吗?您能否详细说明或指出一些有关其工作原理的文档。在这一点上,我很少遇到我不知道的浏览器功能,但似乎就是这样。 -
呃,我不知道浏览器有很多功能,这些功能在 chrome/firefox 中并不总是一致的。您可以深入了解 chromium api 以了解它们如何实现
history。关于历史的 mdn 文档有点蹩脚(有些页面甚至无法加载)developer.mozilla.org/en-US/docs/Web/API/History。就我个人而言,我不会使用历史状态,而是以某种方式自己管理该状态,或者在 url 或 localstorage 或其他东西中对状态进行字符串化 -
可能值得考虑将路径参数设为可选:
path="/product/:productId?"。这样,/product和/product/123将使用相同的组件,并且不会在更改时卸载该组件。
标签: reactjs react-router