显示/隐藏 React 组件不会保持内部状态

Posted

技术标签:

【中文标题】显示/隐藏 React 组件不会保持内部状态【英文标题】:Showing/hiding React components does not maintain internal state 【发布时间】:2021-12-31 13:50:27 【问题描述】:

我正在尝试根据某些状态在 React 中隐藏/显示组件。我面临的主要问题是在隐藏和显示期间保持组件的内部状态。下面是执行我期望的代码并维护每个组件(非洲、欧洲、美洲、亚洲)的状态:

render() 
    const selectedTab = this.state;
    return (
        <div>
            <div className=selectedTab === 'africa' ? '' : 'hidden-tab'><Africa /></div>
            <div className=selectedTab === 'europe' ? '' : 'hidden-tab'><Europe /></div>
            <div className=selectedTab === 'america' ? '' : 'hidden-tab'><America /></div>
            <div className=selectedTab === 'asia' ? '' : 'hidden-tab'><Asia /></div>
        </div>
    )



//regions.scss
.hidden-tab 
   display: none

但是,我对上述代码的简洁性不满意,并想重构,这是我面临的问题。这就是我所做的:

render() 
    const selectedTab = this.state;
    const tabToRegionMap = 
        'africa': <Africa />,
        'eruope': <Europe />,
        'america': <America />,
        'asia': <Asia />
    ;
    const [selectedTab]: selectedRegion, ...regionsToHide = tabToRegionMap;

    return (
        <div>
            <div className='hidden-tab'>
                Object.values(regionsToHide)
            </div>
            selectedRegion
        </div>
    );

上述尝试确实显示/隐藏了组件,但在隐藏/显示期间不保持组件的内部状态 - 似乎每次都在卸载和重新安装它们。

谁能帮我解决问题或提出更好的解决方法?那将不胜感激。

PS 我不希望将状态移动到父级或 Redux,因为这涉及到很多样板,并且各个组件的状态非常复杂。

【问题讨论】:

【参考方案1】:

如果我理解您的问题,您实际上是在寻找一种清理代码的方法保持子组件的安装。

建议的解决方案的问题是,每次渲染并隐藏选项卡时,它都会重新创建元素。它们在渲染到&lt;div className='hidden-tab'&gt; 和不渲染之间切换,每次选择的选项卡更新时都重新安装。

我建议将div 元素抽象为一个有条件地应用'hidden-tab' 类名的新组件。

const Tab = ( children, selectedTab, tab ) => (
  <div className=selectedTab === tab ? '' : 'hidden-tab'>
    children
  </div>
);

...

render() 
  const selectedTab = this.state;
  return (
    <div>
      <Tab selectedTab=selectedTab tab='africa'><Africa /></Tab>
      <Tab selectedTab=selectedTab tab='europe'><Europe /></Tab>
      <Tab selectedTab=selectedTab tab='america'><America /></Tab>
      <Tab selectedTab=selectedTab tab='asia'><Asia /></Tab>
    </div>
  )

如果您想更进一步,您还可以将这些选项卡的包装 div 抽象为一个容器组件,该容器组件存储所选选项卡并通过上下文 API 为子选项卡提供值,因此 selectedTab不需要显式传递给每个。

例子:

import  createContext, useContext  from "react";

const TabContext = createContext(
  selectedTab: null
);

const useSelectedTab = () => useContext(TabContext);

const Tabs = ( children, selectedTab ) => (
  <TabContext.Provider value= selectedTab >children</TabContext.Provider>
);

const Tab = ( children, tab ) => 
  const  selectedTab  = useSelectedTab();
  return (
    <div className=selectedTab === tab ? "" : "hidden-tab">children</div>
  );
;

用法:

render() 
  const selectedTab = this.state;
  return (
    <Tabs selectedTab=selectedTab>
      <Tab tab='africa'><Africa /></Tab>
      <Tab tab='europe'><Europe /></Tab>
      <Tab tab='america'><America /></Tab>
      <Tab tab='asia'><Asia /></Tab>
    </div>
  )

【讨论】:

感谢您的建议@DrewReese!我尝试使用第一个按预期显示/隐藏的解决方案。但是,内部状态仍未维持。知道为什么会这样吗? @John 您有这些国家/地区组成部分之一的示例以及您希望它们维持的那种状态吗?如果它们保持安装状态,那么我不明白为什么即使隐藏状态也不会保持状态。我将在我链接的 CSB 中进行测试。 这里很难粘贴,因为它们是非常复杂的组件,使用我们内部 React 框架中的组件作为主要组件。也许这与我从框架中提取的那些组件有关。 我尝试将新组件放在类方法和 render() 中。这是我要去错的地方吗?像这样:``` buildTabContent() const Tab = ( children, selectedTab, tab ) => ( children ); render() return this.buildTabContent(); ``` @John 这是我的 CSB 的 fork,我在其中为每个 Country 组件添加了一些基本状态,由每个渲染的组件独立更新,甚至将 display: none; 应用于隐藏的组件和它们保持其内部状态。当然,CSB 是我建议的第二个实现,但它实际上只是为您抽象出活动选项卡值。如果没有看到您的更新版本,很难说为什么您的组件没有保持安装状态。

以上是关于显示/隐藏 React 组件不会保持内部状态的主要内容,如果未能解决你的问题,请参考以下文章

在 react-native 中显示/隐藏状态更改的组件时出错

如何使用 React-Bootstrap 和 Redux 显示/隐藏 Modal?

DataGridView隐藏列不会保持隐藏状态

Swift iOS - 即使我隐藏它,导航栏也不会保持隐藏状态

用react做项目时弹窗是用hidden控制显示隐藏的方法还是用组件,组件都有哪些呢

react native 隐藏键盘 TextInput失去焦点