简体   繁体   中英

React callback to parent not changing state

I cannot for the life of me figure out why this isn't working. I have a WorkoutCard component:

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;

And I have the EditWorkoutModal component:

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

The problem here is that closeModalCallback is not changing the state whatsoever. It is called, but modalOpen is still set to true.

And, this is even more confusing, because I have this functionality working in another part of the app. I have a workouts page that has both WorkoutCard components, as well as a Modal, and it works this way. However, the closeModalCallback on the WorkoutCard components' modals will not work.

onClick events bubble up the DOM. For example, see the below snippet (see browser console for output):

 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 />);
 <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>

The above logs the following in the console:

> child
> parent

When you click on your child element, the click event bubbles up the DOM, eventually reaching your div with the WorkoutCard class, which fires the onClick that sets your modal-open state to true . You can stop the event from bubbling by calling e.stopPropagation() on your close-modal button:

onClick={(e) => {
  e.stopPropagation();
  closeModalCallback();
}}

This way the event won't bubble up to your parent div and trigger the onClick which is changing your state.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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