onClick 不会从 Child 组件更新 Parent 的状态

Posted

技术标签:

【中文标题】onClick 不会从 Child 组件更新 Parent 的状态【英文标题】:onClick doesn't update Parent's state from Child component 【发布时间】:2021-06-25 18:57:55 【问题描述】:

我正在尝试使用 Modal.js 本身内部的按钮创建一个可以在单击时关闭的 Modal(弹出窗口)。为了实现这一点,我在 Parent.js 中创建了 useState 并通过 closeModal 函数(它更新了 Parent 的状态)到 Modal.js 中。道具;

无论出于何种原因,onClick 事件都不会更新 Parent 的状态(尽管如此。它设法触发从 props 接受的 closeModal 函数)。从 console.log 我可以看到 closeModal 函数正在运行,但 Parent.js 状态仍然没有改变,因此 Modal 没有关闭。 onMouseDownonChange 等其他事件确实可以正常工作,并且 Modal 已按预期关闭。

能否请您解释一下为什么它不适用于 onClick 以及这里会发生什么?

下面的代码和一个沙盒可以玩:Sandbox

父.js

import  useState  from "react";
import Modal from "./Modal";

export default () => 
  const [modal, setModal] = useState(
    isShown: false,
    name: ""
  );
  const  isShown  = modal;

  const openModal = () => 
    setModal( ...modal, isShown: true );
  ;

  const closeModal = () => 
    setModal( ...modal, isShown: false );
    console.log("Modal must be close!");
  ;

  return (
    <div className="parent" onClick=openModal>
      isShown ? <Modal closeModal=closeModal /> : null
      <div className="message">Open Modal</div>
    </div>
  );
;

Modal.js

export default ( closeModal ) => 
  return (
    <div className="modal">
      <button className="close" onClick=closeModal>
        onClick
      </button>
      <button className="close" onMouseDown=closeModal>
        onMouseDown
      </button>
      <input type="text" placeholder="onChange" onChange=closeModal />
    </div>
  );
;

P.S.:我设法通过移动 onClick 来完成这项工作,这会在 Parent.js 中打开模式,但我仍然不明白为什么它不起作用以及实际发生了什么。我假设使用 onClick 状态更新得如此之快,以至于与旧状态相比,它似乎没有任何区别,因此最终不会更新。但这只是我的猜测......

您能帮我澄清一下吗?

父.js

import  useState  from "react";
import Modal from "./Modal";

export default () => 
  const [modal, setModal] = useState(
    isShown: false,
    name: ""
  );
  const  isShown  = modal;

  const openModal = () => 
    setModal( ...modal, isShown: true );
  ;

  const closeModal = () => 
    setModal( ...modal, isShown: false );
    console.log("Modal must be close!");
  ;

  return (
    <div className="parent">
      isShown ? <Modal closeModal=closeModal /> : null
      <div className="message" onClick=openModal>Open Modal</div>
    </div>
  );
;

【问题讨论】:

【参考方案1】:

您需要停止点击事件传播。由于 Child div 与 Parent(其按钮)重叠,因此两个事件都按顺序发生:

“关闭模态(在child/Modal中)”

“打开模态(在父/按钮中)”

这就是它保持打开状态的原因。要修复它,请在 Modal(子)组件中使用 stopPropagation

<button className="close" onClick=e => 
   e.stopPropagation()
   closeModal()
>

PS:我建议使用this modal

【讨论】:

以上是关于onClick 不会从 Child 组件更新 Parent 的状态的主要内容,如果未能解决你的问题,请参考以下文章

在 onClick 函数中调用更新函数时 useState 不会重新渲染

React Context - Context和Child render没有更新。

Vue - 嵌套组件不会更新其数据并重新渲染

Vue props 数据未在子组件中更新

理解.sync 的用法

ReactJS - Child 的 onClick 事件调用父方法,但范围不是我所期望的