Ruham
Ruham

Reputation: 759

Triggering a function in a React parent functional component from its child

Seen similar issues here, but couldn't wrap my mind on how this works. New to functional components and React overall.

Parent contains the Child, which is a modal. Parent has a div that triggers showing the Child modal, and the Child modal has a close button that triggers its hiding. When I click on the div component in Parent, I need to show and hide the Child modal. When I click on the close button in the Child, I need to hide the Child component.

The Parent component:

import React, { useState } from "react";
import Child from "./Child";

const Parent = () => {
  const [buttonState, setbuttonState] = useState({
    buttonState: false,
  });

  const onParentClick = (e) => {
    e.preventDefault();
    setbuttonState(!buttonState);
  };

  return (
    <div>
      <div onClick={onParentClick}></div>
      <Child isOpen={buttonState} onParentClick={onParentClick} />
    </div>
  );
};

export default Parent;

The Child component:

import React, { useState } from "react";

const Child = (props) => {
  const [buttonState, setButtonState] = useState({
    buttonState: props.isOpen,
  });

  const onChildClick = (e) => {
    e.preventDefault();
    setButtonState(false);
    props.onParentClick();
  };

  return (
    <div
      className={
        buttonState ? "child-modal-opened" : "child-modal-closed"
      }
    >
      <div onClick={onChildClick}>Close</div>
    </div>
  );
};

export default Child;

For some reason, can't make this work. What am I missing here?

Upvotes: 0

Views: 1362

Answers (2)

Vitalii
Vitalii

Reputation: 2131

Looks like useState() is used incorrectly.

const [buttonState, setbuttonState] = useState({
    buttonState: false,
  });

results in buttonState being { buttonState: false}, so setbuttonState(!buttonState) does not work as intended.

Here's updated Parent component with useState(false) instead (setting initial buttonState value to false)

import React, { useState } from "react";
import Child from "./Child";

const Parent = () => {
  const [buttonState, setbuttonState] = useState(false);

  const onParentClick = (e) => {
    e.preventDefault();
    setbuttonState(!buttonState);
  };

  return (
    <div>
      <div onClick={onParentClick}></div>
      <Child isOpen={buttonState} onParentClick={onParentClick} />
    </div>
  );
};

export default Parent;

P.S.

As @Will suggested, there is no need to create another state in Child, it can be passed from Parent

import React, { useState } from "react";

const Child = (props) => {
  return (
    <div
      className={
        props.isOpen ? "child-modal-opened" : "child-modal-closed"
      }
    >
      <div onClick={props.onParentClick}>Close</div>
    </div>
  );
};

Upvotes: 3

Dom Eccleston
Dom Eccleston

Reputation: 59

It looks like onParentClick is defined so as to take an event object as a parameter and call preventDefault() on that, but you're calling it without any arguments. Does it work like this: props.onParentClick(e);?

Upvotes: 0

Related Questions