react-router如何在页面刷新时保持位置状态?

Geo*_*uer 11 reactjs react-router

我很困惑.

我有一个工作流程,有人可以开始填写产品的表格.这是一个很长的形式,我想在他们输入时将进度保存到服务器(但直到他们填写了一点).所以我们从创建表单的url开始,在他们输入一点后,我们POST在服务器上创建一个资源,在请求完成后,我们用新id更新url到编辑路径.

换句话说,你开始在网址填写表格/product然后在你填写了一些网址转移到/product/123.之后,加载该URL会为您提供表单.

所以基本上我有

<Route path={`/product`} exact component={CreateProduct} />
Run Code Online (Sandbox Code Playgroud)

<Route exact={true} path="/product/:productId" render={({
      match: {params: {productId}},
      location: {state: {data}={}}
  }) => (
    <EditProduct productId={productId} initialData={data} 
  )} />
Run Code Online (Sandbox Code Playgroud)

看到那个州?那是因为我从创建切换到编辑模式的方式是这样的

const id = await apiFetch(`/api/product`, data, {method: `POST`})
this.props.history.push({pathname: `/product/${id}`, state: {data} })
Run Code Online (Sandbox Code Playgroud)

在我的<EditProduct>组件的构造函数中我有

constructor({productId, initialData}) {
   this.super()
   this.state = {}
   if(initialData)
     this.setState({data: initialData})
   else
     getProduct(productId).then(({data}) => this.setState({data}))
}
Run Code Online (Sandbox Code Playgroud)

通过这样做,进入的初始数据<EditProduct><CreateProduct>组件播种,我不需要从服务器或任何东西重新加载它.

这工作,过渡是顺利的,网址更新,一切都是hunky dory.

我现在可以继续编辑<EditProduct>组件并正确保存.我可以打开一个新标签到同一个网址,它会加载所有内容,我可以继续.发生这种情况initialData是因为在那种情况下它是undefined从服务器加载的.好极了!

如果我改为刷新原始标签,事情会变得奇怪.自保存以来累积的任何更改都将丢失.在调试器中向下钻取我发现问题是initialDatalocation.state.data对象传递的不是空的 - 它是从第一次创建产品时开始的初始对象.

那它究竟来自哪里呢?我只是进行了整页刷新(即使是"硬"刷新,没有缓存和devtools打开).该数据不在URL中(事实上,将URL粘贴到同一窗口中的另一个选项卡中没有此问题).

我所知道的唯一机制可以在刷新时保留数据,但不能保存到像这样的新标签sessionStorage,但是当我在控制台中检查它时,我被告知

> sessionStorage
< Storage {length: 0}
Run Code Online (Sandbox Code Playgroud)

我甚至认为可能路由器在页面卸载之前和加载之后操作会话存储,但是在我的javascript包的第一行打破显示完全相同的事情.

那么这种持久性究竟是怎么发生的呢?

Gui*_*chi 6

我相信提问者已经解决了这个问题,但答案隐藏在评论中。

这个问题实际上可以归结为:

state当用户重新加载页面时,信息从何而来?并stateprops.location.state由提供react-router

太长了;这state不是一个简单的 javascript 实现,它绑定到浏览器环境

直接BroswerRouter使用react-router底层本机浏览器历史记录 API,因此历史记录 API 与平台绑定,您无法根据正常规则预测其行为。

这是特别的部分:

状态对象可以是任何可以序列化的对象。因为 Firefox 将状态对象保存到用户的磁盘中,以便在用户重新启动浏览器后可以恢复它们

大多数用户将其视为state普通的 javascript,因此存在问题


ped*_*erk 1

我有一个非常相似的问题,也有同样的困惑。

用window.history.replaceState()解决了它

我有一个简单的搜索表单,它重定向到第二页,并使用路由器的位置状态重新填充第二页上的搜索输入。

就我而言,发生了这种情况:

  1. 在第一页搜索“foo” -> 重定向到第二页,并查看“foo”的搜索+结果。
  2. 在第二页上搜索“bar”。-> 查看“bar”的结果。
  3. 点击刷新。期待?要么是空搜索栏,要么是“bar”的搜索+结果。-> 相反,请查看“foo”的搜索+结果(??)

我解决了这个问题,每次用户在第二页上进行搜索时,我都会用window.history.replaceState正确的搜索词替换状态。这样,刷新即可为用户提供预期的搜索。在第二页的每次搜索中用空对象替换状态也效果很好,在每次刷新时为用户提供空搜索。