AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / coding / 问题 / 77106631
Accepted
Sougata Mukherjee
Sougata Mukherjee
Asked: 2023-09-15 00:00:39 +0800 CST2023-09-15 00:00:39 +0800 CST 2023-09-15 00:00:39 +0800 CST

如何防止子组件在react中渲染到父组件上

  • 772

在这里,我在父组件中创建了一个重新渲染的切换按钮,在子组件中创建了一个加号按钮,计数器要求是切换按钮重新渲染是一个将隐藏和显示组件的切换按钮,但如果有最后一个计数器添加,例如从0到2,隐藏和显示后它应该保持不变,就像2而不是0,但问题是我无法隐藏子组件,那么我该如何隐藏和显示子组件并维护子状态?基本上,通过渲染父级,我想继续维护子级状态值。父代码是

import React, { useRef, useState, useMemo } from 'react';
import DropDown from './DropDown';

function App() {
  const shouldRenderChild = useRef(true);
  const [hide, setHide] = useState(false);

  const toggleChildRendering = () => {
    shouldRenderChild.current = !shouldRenderChild.current;
    setHide(!hide);
  };

  const MemoizedDropDown = useMemo(() => {
    return shouldRenderChild.current ? <DropDown /> : null;
  }, []);

  return (
    <div>
      <button onClick={toggleChildRendering}>
        Toggle Child Rendering
      </button>
      {MemoizedDropDown}
    </div>
  );
}

export default App;

子代码是

import React, { useState } from "react";
export default function DropDown() {
  const [number, setNumber] = useState(0);
  return (
    <>
      <button onClick={() => setNumber(number + 1)}>+</button>
      <div>Child Component{number}</div>
    </>
  );
}
javascript
  • 3 3 个回答
  • 33 Views

3 个回答

  • Voted
  1. Best Answer
    Sergey Sosunov
    2023-09-15T00:28:32+08:002023-09-15T00:28:32+08:00

    每次安装或卸载组件(使用条件渲染)时,组件的状态都会将自身重新设置为默认值。所以这就是你的问题,useMemohook 在这里帮不了你。

    要解决您的问题,您可以修改根 css 文件并添加类似类的.hidden内容:

    .hidden {
      display: none;
    }
    

    很可能您的项目中已经有了这种实用程序类。就像d-none引导程序或类似的。

    接下来 - 您需要向DropDown组件添加一个包装器,或者将该组件返回的根节点的类型更改为React.Fragmentie以外的其他类型<> </>,并对其应用条件,className如下所示:

    className={hide ? 'hidden' : ''}
    

    这是解决方案的示例:

    import React, { useState } from 'react';
    
    function DropDown({ className }) {
      const [number, setNumber] = useState(0);
      return (
        <div className={className}>
          <button onClick={() => setNumber(number + 1)}>+</button>
          <div>Child Component: {number}</div>
        </div>
      );
    }
    
    export const App = () => {
      const [hide, setHide] = useState(false);
    
      const toggleChildRendering = () => {
        setHide(!hide);
      };
    
      return (
        <div>
          <button onClick={toggleChildRendering}>Toggle Child Rendering</button>
          <DropDown className={hide ? 'hidden' : ''} />
        </div>
      );
    };
    

    Stackblitz演示

    • 1
  2. Benny Bennett
    2023-09-15T00:10:51+08:002023-09-15T00:10:51+08:00

    您的方法的主要问题是您使用的useMemo方式错误。useMemo缓存计算值(在本例中为组件),并且仅在其依赖项之一发生更改时才会重新计算该值。您应该使用useMemo来决定是否渲染DropDown组件,并作为该决定的依赖项,使用hide.

    这是更详细的解决方案:

    父组件: 我们将使用hide状态来确定是否应该显示子组件。我们将用来useMemo缓存子组件。如果hide发生变化,则会重新计算是否显示子组件。

    import React, { useState, useMemo } from 'react';
    import DropDown from './DropDown';
    
    function App() {
      const [hide, setHide] = useState(false);
    
      const toggleChildRendering = () => {
        setHide(!hide);
      };
    
      const MemoizedDropDown = useMemo(() => {
        return !hide ? <DropDown /> : null;
      }, [hide]);
    
      return (
        <div>
          <button onClick={toggleChildRendering}>
            Toggle Child Rendering
          </button>
          {MemoizedDropDown}
        </div>
      );
    }
    
    export default App;
    

    子组件: 这保持不变。它只是显示一个增加计数器的按钮。

    import React, { useState } from "react";
    
    export default function DropDown() {
      const [number, setNumber] = useState(0);
      return (
        <>
          <button onClick={() => setNumber(number + 1)}>+</button>
          <div>Child Component: {number}</div>
        </>
      );
    }
    

    通过遵循这种方法,您可以显示/隐藏子组件,而不会丢失其内部状态。但是,请注意,如果子组件被卸载(即从 DOM 中完全删除)然后重新安装,其内部状态将被重置。如果即使组件已卸载也想保留状态,则需要更复杂的解决方案,例如使用上下文或将状态向上移动到父组件并将其作为 props 向下传递。

    • 0
  3. Saahil M
    2023-09-15T00:51:43+08:002023-09-15T00:51:43+08:00

    解决这个问题的简单方法是提升国家地位。

    1. 基本上,如果您使用条件隐藏组件,则在为真!hide ? <DropDown /> : null时它将被卸载。hide
    2. 现在,当您存储number儿童状态时,它也会消失。
    3. 因此,如果您将该number值存储在父级的状态中,它就会持续存在。
    4. 现在,如果子组件由于hide标志为 true 而被卸载,您仍然可以将状态保存在 Parent 中。
    5. 这样,您可以隐藏/显示子组件,并且状态将被保留。
    6. 我不建议你用 CSS 隐藏组件。但是,如果这对您来说是一个特殊的用例,那么您可以使用该hide标志来设置子组件的样式display: none

    <下拉样式={{显示:隐藏?'无' : '阻止' }} ... />

    正确的方式:

    应用程序.js

    function App() {
      const [number, setNumber] = useState(0);
      const [hide, setHide] = useState(false);
      ...
      return (
        ...
        <Dropdown number={number} changeNumber={setNumber} />
      )
    }
    

    Dropdown.js

    export default function DropDown({number, changeNumber}) {
      return (
        <>
          <button onClick={() => changeNumber(number + 1)}>+</button>
          <div>Child Component{number}</div>
        </>
      );
    }
    
    • 0

相关问题

  • 合并排序不起作用 - Javascript代码:即使在调试后也无法找到错误

  • select.remove() 方法工作得很奇怪[关闭]

  • useOpenWeather() 中总是出现 401 res -react-open-weather lib [重复]

  • 输入元素没有只读属性,但字段仍然不可编辑[关闭]

  • 如何编辑 D3.js RadialTree 的第一个节点半径?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    使用 <font color="#xxx"> 突出显示 html 中的代码

    • 2 个回答
  • Marko Smith

    为什么在传递 {} 时重载解析更喜欢 std::nullptr_t 而不是类?

    • 1 个回答
  • Marko Smith

    您可以使用花括号初始化列表作为(默认)模板参数吗?

    • 2 个回答
  • Marko Smith

    为什么列表推导式在内部创建一个函数?

    • 1 个回答
  • Marko Smith

    我正在尝试仅使用海龟随机和数学模块来制作吃豆人游戏

    • 1 个回答
  • Marko Smith

    java.lang.NoSuchMethodError: 'void org.openqa.selenium.remote.http.ClientConfig.<init>(java.net.URI, java.time.Duration, java.time.Duratio

    • 3 个回答
  • Marko Smith

    为什么 'char -> int' 是提升,而 'char -> Short' 是转换(但不是提升)?

    • 4 个回答
  • Marko Smith

    为什么库中不调用全局变量的构造函数?

    • 1 个回答
  • Marko Smith

    std::common_reference_with 在元组上的行为不一致。哪个是对的?

    • 1 个回答
  • Marko Smith

    C++17 中 std::byte 只能按位运算?

    • 1 个回答
  • Martin Hope
    fbrereto 为什么在传递 {} 时重载解析更喜欢 std::nullptr_t 而不是类? 2023-12-21 00:31:04 +0800 CST
  • Martin Hope
    比尔盖子 您可以使用花括号初始化列表作为(默认)模板参数吗? 2023-12-17 10:02:06 +0800 CST
  • Martin Hope
    Amir reza Riahi 为什么列表推导式在内部创建一个函数? 2023-11-16 20:53:19 +0800 CST
  • Martin Hope
    Michael A fmt 格式 %H:%M:%S 不带小数 2023-11-11 01:13:05 +0800 CST
  • Martin Hope
    God I Hate Python C++20 的 std::views::filter 未正确过滤视图 2023-08-27 18:40:35 +0800 CST
  • Martin Hope
    LiDa Cute 为什么 'char -> int' 是提升,而 'char -> Short' 是转换(但不是提升)? 2023-08-24 20:46:59 +0800 CST
  • Martin Hope
    jabaa 为什么库中不调用全局变量的构造函数? 2023-08-18 07:15:20 +0800 CST
  • Martin Hope
    Panagiotis Syskakis std::common_reference_with 在元组上的行为不一致。哪个是对的? 2023-08-17 21:24:06 +0800 CST
  • Martin Hope
    Alex Guteniev 为什么编译器在这里错过矢量化? 2023-08-17 18:58:07 +0800 CST
  • Martin Hope
    wimalopaan C++17 中 std::byte 只能按位运算? 2023-08-17 17:13:58 +0800 CST

热门标签

python javascript c++ c# java typescript sql reactjs html

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve