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
Above is a gif of the behaviour
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".
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>
</>
);
};