繁体   English   中英

React中的条件渲染会在切换时导致重新安装

[英]Conditional rendering in React that causes remounting when toggled

我最近一直在与React挣扎,试图了解如何正确控制可以通过几种不同的方式显示的有条件渲染的元素(例如对话框)。 例如,项目列表可能每个都有自己的模式内容,但仍共享相同的模式。 我只是在不需要时隐藏模式( display: none ),并在需要时更改显示。

问题是,每次显示时都需要重新初始化模态。 举例来说,模式包含一系列选项卡,当前选项卡索引存储在模式状态中。 在关闭并重新打开模态后,我希望当前的Tab索引将重置为零,但是事实并非如此。 而是隐藏模态之前剩下的一切。

这样做的一个很明显的原因是,模态在最初渲染时只被安装了一次 随后的渲染更新不会重新运行安装生命周期方法。 显然,解决方案必须包括在需要时重新安装组件(通常在再次显示时)。

我想出了一个可能的示例– isDialogShown更改时, isDialogShown应卸载并重新安装Dialog 我相当确定React能够注意到这一点,并在isDialogShown标志更改后能够正确运行生命周期方法。

...
const ParentElement = ({ isElementShown }) => {
  return (
    {!Boolean(isElementShown) 
      ? null
      : <ConditionalElement prop={stuff} />
    }
  );
}
...

CodePen示例-条件渲染

但是,我不确定这是否是最好的方法。 我希望有一种方法可以将属性传递给ConditionalElement本身,从而使它重新呈现。 如果属性是某个值,也许从render()函数返回null 问题是我认为这不会重置ConditionalElement本身,但可能会重置所有子项。

const ParentElement = ({ isElementShown }) => {
  return (
      <ConditionalWrapper isShown={true}>
        <ConditionalElement />
      <ConditionalWrapper/>
    }
  );
}

const ConditionalWrapper = ({ children, isShown }) = {
  // Don't render any children if the element should be hidden
  // Also, styles would be applied to hide the wrapper if necessary
  if (!isShown) {
    return null;
  }

  // Render the children if not hidden
  return children;
};

第二种方式似乎不那么“ hacky”,但嵌套也更多。 还是会推荐吗? 令人高兴的是,如果应该保留本地状态,两种方式都可以“切换”元素(取消/重新安装)和“隐藏”元素( display: none; )。 这仅需要另一个参数( isToggledisShown )。

IMO的第二种方法是可以的,但是,如果您不喜欢嵌套的结果,则可以创建一个高阶组件(HOC)来增强组件的行为,增强组件的工作原理与原始组件相同,只是知道例如,一个“ shouldRender”属性,可在和之间切换基础组件。

const toTogglable = (Elem) => (props) =>
  props.shouldRender ? <Elem {...props}/> : null;

const TogglableA = toTogglable(A);
// Then you can use it like
// <TogglableA shouldRender={true} {...otherProps} />

这种方法的另一个优点是您可以免费获得可组合性,例如,如果您想通过属性“ shouldHide”来概括显示/隐藏的行为,则可以创建另一个HOC,然后只需组合它们以增强您的组件,结果就是始终是一个平面组件。

根据您的实际情况,查看http://codepen.io/anon/pen/MmzpdG以获取可用的示例。

暂无
暂无

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

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