2
votes

I have simple Reactjs app that includes the Card and Modal components. every Card must have a Modal that when clicking on "Show More" button, open it.

Modal should only show the title on its Card and my problem is passed props to Modal, just send the title of the last Card And not about itself!

In summary, the prop of title received properly in Card component but Card component can't pass title to Modal correctly.

Here is my app in CodeSandBox: Demo

Card Components:

const Card = props => {
  const { children, title } = props;
  const { isShowModal, setIsShowModal } = useContext(MainContext);

  const showModalHandler = () => {
    setIsShowModal(true);
  };

  return (
    <div className="card">
      <div className="card-header">
        <h2>{title}</h2>
      </div>

      <div className="card-content">{children}</div>
      <div className="card-footer">
        <button onClick={showModalHandler}>Show More</button>
      </div>

      {isShowModal && <Modal title={title} />}
    </div>
  );
};

Modal Component:

const Modal = props => {
  const { setIsShowModal } = useContext(MainContext);

  const closeModalHandler = () => {
    setIsShowModal(false);
  };

  const { title } = props;

  return (
    <div className="modal">
      <h2>Modal: {title}</h2>
      <p>
        You cliked on <b>{title}</b> Card
      </p>
      <hr />
      <button onClick={closeModalHandler}>Close</button>
    </div>
  );
};

Note: I use Context for control open/close modal in isShowModal state and maybe that's the problem?

1
The actual problem is not very clear from your description - William
@William Please see the demo. title not pass correctly to modal. - Amir

1 Answers

2
votes

Just as you thought the problem seems to be the useContext that you are using. So I made a couple of changes to the code, most importantly using useState. I recommend you read the documentation about useContext and when to use it. Here is the updated code:

Card.js

import React, { useState } from "react";
import Modal from "./Modal";
import "./Card.scss";

const Card = props => {
  const { children, title } = props;
  const [ isShowModal, setIsShowModal ] = useState(false);


  return (
    <div className="card">
      <div className="card-header">
        <h2>{title}</h2>
      </div>

      <div className="card-content">{children}</div>
      <div className="card-footer">
        <button onClick={() => setIsShowModal(true)}>Show More</button>
      </div>

      {isShowModal && <Modal setIsShowModal={setIsShowModal} title={title} />}
    </div>
  );
};

export default Card;

Modal.js

import React from "react";
import "./Modal.scss";

const Modal = props => {

  const { title } = props;

  return (
    <div className="modal">
      <h2>Modal: {title}</h2>
      <p>
        You cliked on <b>{title}</b> Card
      </p>
      <hr />
      <button onClick={() => props.setIsShowModal(false)}>Close</button>
    </div>
  );
};

export default Modal;

As you can see, Modal.js component doesn't have to be a stateful component. You can pass as a prop the setIsShowModal function from Card.js component. That way you can make the modal a reusable component.