简体   繁体   English

使用react-router在路由之间保留组件

[英]Keep components between routes using react-router

I have a multi-steps form and I'm using react-router to navigate between the different steps. 我有一个多步骤的表单,我正在使用react-router在不同的步骤之间导航。 In some of the steps I show an iframe to the user. 某些步骤中,我向用户显示iframe。 When the user navigates between steps it always unmount and re-mount the iframe, this causes two problems: 当用户在步骤之间导航时,它总是卸载并重新安装iframe,这会导致两个问题:

  1. It reloads the iframe from its source, which makes it jump. 它从其源重新加载iframe,这使它跳转。
  2. Since it's an iframe I can't control its internal state and it loses the state between steps. 由于它是一个iframe,我无法控制其内部状态,并且它会失去步骤之间的状态。 So if the user had some inputs to the iframe, when moving to the next step the inputs are lost. 因此,如果用户对iframe有一些输入,则在移动到下一步时输入会丢失。

Is there any way to keep the iframe instance in some global store and only mount it to the DOM when necessary ? 有没有办法将iframe实例保存在某个全局存储中,并且只在必要时将其挂载到DOM?

Any other ideas how to solve this problem ? 任何其他想法如何解决这个问题?

Thanks. 谢谢。

Is there any way to keep the iframe instance in some global store and only mount it to the DOM when necessary ? 有没有办法将iframe实例保存在某个全局存储中,并且只在必要时将其挂载到DOM?

Yes, you could, but if you even remove an iframe from the DOM and re-append it later it still gets reloaded, so in that way the problem actually has very little to do with React's component tree. 是的,你可以,但如果你甚至从DOM中删除iframe并在以后重新附加它仍然会重新加载,所以这样问题实际上与React的组件树几乎没有关系。 What you really need is to just hide your iframe and show it again later. 你真正需要的是隐藏你的iframe并稍后再显示它。

You could of course hide and show the iframe in React like this: 您当然可以在React中隐藏和显示iframe,如下所示:

{ <iframe src="..." style={{display: this.state.showing ? "block" : "none"}} /> }

In this case you need to render the iframe at some place that does not get unmounted. 在这种情况下,你需要渲染的iframe在一些地方没有得到卸载。 You can use components further down in your tree to communicate back upwards to show/hide the iframe. 您可以使用树中更下方的组件向上通信以显示/隐藏iframe。


But if you really want to be able to hide/show the iframe from different places in your component tree that get mounted and unmounted, you can, but it gets quite a bit trickier and not a typical use-case of React. 但是如果你真的希望能够隐藏/显示组件树中不同位置的iframe,那么你可以,但是它会变得相当棘手,而不是典型的React用例。

You'll need to create the DOM iframe yourself and append it somewhere into the DOM that is outside React's component tree (this is generally an anti-pattern in React). 您需要自己创建DOM iframe并将其附加到React的组件树之外的DOM中(这通常是React中的反模式)。 Then you can use a proxy component to show/hide this DOM element when mounted and unmounted. 然后,您可以使用代理组件在安装和卸载时显示/隐藏此DOM元素。

Here's an example that appends an iframe to the document.body and shows it when a component is mounted, and hides it when the component is unmounted: 这是一个将iframe附加到document.body的示例,并在安装组件时显示它,并在卸载组件时隐藏它:

class WebView extends React.Component {
  static views = {};
  componentDidMount() {
    if (!WebView.views[this.props.url]) {
      WebView.views[this.props.url] = this.createWebView(this.props.url);
    }
    WebView.views[this.props.url].style.display = "block";
  }
  componentWillUnmount() {
    WebView.views[this.props.url].style.display = "none";
  }
  createWebView(url) {
    let view = document.createElement("iframe");
    view.src = this.props.url;
    document.body.appendChild(view);
    return view;
  }
  render() {
    return null;
  }
}

Here it is working on CodePen : notice that when you hide (unmount) then show (mount) the WebView the iframe state (for example search input) stays the same. 这是在CodePen上工作 :请注意,当您隐藏(卸载)然后显示(挂载) WebView ,iframe状态(例如搜索输入)保持不变。

You will also need to position and size the iframe to appear within your layout correctly. 您还需要将iframe的位置和大小设置为正确显示在布局中。 I haven't shown this because it's a bit difficult to solve generally. 我没有表现出来,因为一般来说解决起来有点困难。

Note that this solution is similar to the "portal" pattern . 请注意,此解决方案类似于“门户”模式 The difference here is to not ever unmount the iframe in order to preserve its state and prevent reloading. 这里的区别是不要卸载iframe以保持其状态并防止重新加载。

Quite simply, there's no way to preserve a component in the render tree if the parent is not rendered. 很简单,如果未渲染父级,则无法在渲染树中保留组件。 That is, when the route changes, your component will necessarily be unmounted if it's a child to a Route . 也就是说,当路线发生变化时,如果它是Route的孩子,则必须卸下您的组件。

One way to side-step that is to make your component not a child to any Route at all . 侧面步骤的一种方法是使您的组件根本不是任何路径的子组件。 This way, you would always render this component alongside every Route. 这样,您始终会将此组件每个Route 一起呈现。 Then you can simply use styles to show/hide it when appropriate. 然后,您可以在适当的时候使用样式来显示/隐藏它。 Obviously, this will partly compromise the structure of your DOM. 显然,这将部分地破坏DOM的结构。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM