1

I want to implement update functionality in react. What I created is that I have an Update button, when it is clicked, a modal pops up with an input field to enter the updated value. But as soon as I type a single character, it closes and opens again (attached gif). Attached below is the code of React Component and gif.

import React , {useState} from'react';
import { Button,Form,Modal } from 'react-bootstrap';


const handleShowModal = (i) => {
    setModalShow(true);
}

const handleCloseModal = () => {
    setModalShow(false);
}

const handleCommentChange = (event) => {
    setModalInputComment(event.target.value);
}


function MyVerticallyCenteredModal(props) {

    return (
        <Modal
            {...props}
            size="lg"
            aria-labelledby="contained-modal-title-vcenter"
            centered
        >
        <Modal.Body>
          <Form>
              <div className="mb-3">
                <label  className="col-form-label">Username:</label>
                <input type="text" className="form-control" id="comment" />
              </div>
              <div className="mb-3">
                <label  className="col-form-label">Comment:</label>
                <textarea className="form-control" id="comment-text" value={modalInputComment} onChange={handleCommentChange}></textarea>
              </div>
          </Form>
        </Modal.Body>
        <Modal.Footer>
            <Button >Update</Button>
            <Button variant='secondary' onClick={handleCloseModal}>Close</Button>
        </Modal.Footer>
      </Modal>
    );
  }

  const [modalShow, setModalShow] = useState(false);
  
  const [modalInputComment, setModalInputComment] = useState();

  

return(
<>
    <div>
        {comments.map((item,key)=>(
            <div className="comment" key={key}>
                <h4>{item.username}</h4>
                <p>{item.text}</p>
                <Button variant="outline-primary btn-sm mx-3" onClick={() => handleShowModal(key)}>Update</Button>
            </div>

        ))}

        <MyVerticallyCenteredModal show={modalShow} />

    </div>

  </>
  )
 };

 export default CommentsList;

This is the comments array passed as props

This is the comments array passed as props

enter image description here

Above is a gif of the behaviour

MagnusEffect
  • 3,363
  • 1
  • 16
  • 41

1 Answers1

2

Issue

From what I can tell you are redeclaring the MyVerticallyCenteredModal within another component, so each time the component's state updates or is otherwise rerendered, a new MyVerticallyCenteredModal component is created. This will unmount the previous "instance" and mount a new "instance".

Solution

Move the MyVerticallyCenteredModal component definition outside any other components, pass all the appropriate props.

function MyVerticallyCenteredModal({
  modalInputComment, // <-- destructure props
  handleCommentChange, // <-- destructure props
  ...props
}) {
  return (
    <Modal
      {...props}
      size="lg"
      aria-labelledby="contained-modal-title-vcenter"
      centered
    >
      <Modal.Body>
        <Form>
          <div className="mb-3">
            <label className="col-form-label">Username:</label>
            <input type="text" className="form-control" id="comment" />
          </div>
          <div className="mb-3">
            <label className="col-form-label">Comment:</label>
            <textarea
              className="form-control"
              id="comment-text"
              value={modalInputComment}
              onChange={handleCommentChange}
            />
          </div>
        </Form>
      </Modal.Body>
      <Modal.Footer>
        <Button >Update</Button>
        <Button variant='secondary' onClick={handleCloseModal}>Close</Button>
      </Modal.Footer>
    </Modal>
  );
}

Component

  ...

  const handleShowModal = (i) => {
    setModalShow(true);
  }

  const handleCloseModal = () => {
    setModalShow(false);
  }

  const handleCommentChange = (event) => {
    setModalInputComment(event.target.value);
  }

  const [modalShow, setModalShow] = useState(false); 
  const [modalInputComment, setModalInputComment] = useState();

  return(
    <>
      <div>
        {comments.map((item,key)=>(
          <div className="comment" key={key}>
            <h4>{item.username}</h4>
            <p>{item.text}</p>
            <Button
              variant="outline-primary btn-sm mx-3"
              onClick={() => handleShowModal(key)}
            >
              Update
            </Button>
          </div>
        ))}

        <MyVerticallyCenteredModal
          show={modalShow}
          modalInputComment={modalInputComment} // <-- pass props
          handleCommentChange={handleCommentChange} // <-- pass props
        />
      </div>
    </>
  );
};
Drew Reese
  • 165,259
  • 14
  • 153
  • 181