繁体   English   中英

防止组件在 DOM 的不同部分显示时卸载

[英]prevent component from unmounting when displayed in different parts of the DOM

我的应用程序的布局会根据用户所做的某些选择而发生变化,因此相同的组件会挂在 DOM 中的不同节点下。 不幸的是,React 卸载并重新安装组件。 结果,我的组件丢失了状态已累积。 我试图添加一个key属性来传达信息,即这是同一个实例,但我得到了相同的结果。 下面显然是一个SSCCE。 每次用户单击按钮时,组件A都会卸载并重新安装:

class A extends React.Component {
  componentWillUnmount = () => {
    console.log('map::componentWillUnmount()');
  }

  componentDidMount = () => {
    console.log('map::componentDidMount()');
  }
  render() {
    return (
      <div>
        this is component A
      </div>
    );

  }
}


class App extends React.Component {

  constructor(props) {
    super(props);
    this.state={i:0};
  }

  increment = () => {
    this.setState({i: this.state.i+1});
  }


  render() {
    console.log('app::render');
    if (this.state.i % 2 === 0)
      return (
        <>
        <div>
          <div>
            <A key={42}/>
          </div>
        </div>
        <button onClick={this.increment}>re-render</button>
        </>
      );
    else return (
      <>
      <div>
        <A key={42}/>
      </div>
      <button onClick={this.increment}>re-render</button>
      </>
    )
  }
}

只是为了澄清,我的代码除了重现问题之外并没有试图实现任何目标,就像我说的那样,这是一个 SSCCE。 当然,在某些应用程序中,用户可以从“首选项”菜单更改布局,以便组件根据用户的首选项最终位于 DOM 中的不同位置。 我无法想象在这种情况下失去状态是可以接受的。 处理这种情况的正确方法是什么?

这是因为条件渲染返回两个不同的树结构,其中A的路径不同。

  • React.Fragment > div > div > A
  • React.Fragment > div > A


想象一下,如果我们通过使用普通的 JS 来模拟 React 来手动安装和卸载,我们将不得不:

  1. <A/>存储为变量
  2. 删除内部<div/><A/>也会自动删除)
  3. 然后将先前存储的<A/>附加到外部<div/> (这实际上不是一个好方法,因为这假设<A/>一旦安装就永远不需要更新自己,即使道具发生变化)

只要有 remove 和 append,就相当于卸载了一个 React 组件,然后再次安装。


代码有点含糊,我无法通过在第一个条件中拥有 2 个<div/>并且在第二个条件中只有 1 个<div/>来判断它试图实现什么。 但也许您可以使用三元运算符来有条件地呈现您需要的内容,而将<A/>单独<A/> (并且可能是一些 CSS 以使内部<div/>看起来好像嵌套在另一个<div/> ) . 这样,当<App/>改变状态时<A/>不会卸载。

return (
  <>
    <div>
      <A />
      {condition ? // where `condition` is a boolean
        <div style={{
          position: 'absolute'
          // and may be other styles to achieve the visual trickery
        }}>
          {/* your content here */}
        </div>
        :
        null
      }
    </div>
    <button onClick={this.increment}>re-render</button>
  </>
)

顺便说一句,他们说 42 是所有问题的答案,但我认为不是这种情况。 将密钥设置为 42 无济于事。 😅

暂无
暂无

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

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