对父级未更改状态的回调做出反应

joh*_*ter 2 javascript state reactjs react-hooks

我一生都无法弄清楚为什么这不起作用。我有一个 WorkoutCard 组件:

锻炼卡:

const key = require('weak-key');

function WorkoutCard({ workout }) {

  const { userID } = useContext(AuthContext);
  const [modalOpen, setModalOpen] = useState(false);
  const closeModalCallback = () => setModalOpen(false);

  return (
    <div className="WorkoutCard" onClick={() => setModalOpen(true)}>
      <div className="header">
        <h2>{workout.name}</h2>
        <h3>Days</h3>
        {workout.days.map((day) => {
          return (
            <p key={key({})}>{day}</p>
          )
        })}
        <button className="deleteButton" onClick={handleDelete}>Delete</button>
      </div>

      <div className="line"></div>

      <div className="exercises">
        <h3>Exercises</h3>
        {workout.exercises.map((exercise) => {
          return (
            <p key={key({})}>{exercise}</p>
          )
        })}
      </div>

      <EditWorkoutModal key={key({})} modalOpen={modalOpen} closeModalCallback={closeModalCallback} />
    </div>
  );
}

export default WorkoutCard;
Run Code Online (Sandbox Code Playgroud)

我有 EditWorkoutModal 组件:

Modal.setAppElement('#root');

function EditWorkoutModal({ modalOpen, workout, closeModalCallback }) {

  const { userID } = useContext(AuthContext);

  return (
    <Modal isOpen={modalOpen} className="editModal">
      <div className="rightHalf">
        <p className='closeButton' onClick={() => closeModalCallback()}>+</p>
      </div>
    </Modal>
  )
}

export default EditWorkoutModal
Run Code Online (Sandbox Code Playgroud)

这里的问题是 closeModalCallback 没有改变任何状态。它被调用,但 modalOpen 仍设置为 true。

而且,这更令人困惑,因为我在应用程序的另一部分工作了此功能。我有一个锻炼页面,其中包含 WorkoutCard 组件和模态框,并且它以这种方式工作。但是,WorkoutCard 组件模态上的 closeModalCallback 将不起作用。

Nic*_*ons 5

onClick事件在 DOM 中冒泡。例如,请参阅以下代码片段(请参阅浏览器控制台以获取输出):

const App = () => {
  const parent = () => console.log("parent");
  const child = () => console.log("child");
  return <div onClick={parent}>
    <div onClick={child}>Click me</div>
  </div>
}

ReactDOM.createRoot(document.body).render(<App />);
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.0.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.0.0/umd/react-dom.production.min.js"></script>
Run Code Online (Sandbox Code Playgroud)

上面在控制台中记录了以下内容:

> child
> parent
Run Code Online (Sandbox Code Playgroud)

在您的情况下,当您单击子元素时,单击事件会在 DOM 中向上冒泡,最终到达divWorkoutCard组件中的父元素,这会触发onClick将模态打开状态设置回 的truee.stopPropagation()您可以通过调用关闭模式按钮的事件参数来阻止事件冒泡:

onClick={(e) => {
  e.stopPropagation();
  closeModalCallback();
}}
Run Code Online (Sandbox Code Playgroud)

这样,事件就不会冒泡到您的父级 div 并触发onClick正在改变您的状态的事件。