In order to not duplicate state I would enclose the inputs in the modal in a form element and convert the inputs to uncontrolled inputs. When the form is submitted grab the form field values and pass in the formData callback and reset the form. Explicitly declare the button to be type="submit".
const Modal = (props) => {
const onFormSubmit = (e) => {
e.preventDefault();
const firstName = e.target.firstName.value;
const lastName = e.target.lastName.value;
props.formData({ firstName, lastName });
e.target.reset();
};
if (!props.show) {
return null;
} else {
return (
<div className="modal" id="modal">
<form onSubmit={onFormSubmit}>
<input type="text" name="firstName" />
<input type="text" name="lastName" />
<button className="toggle-button" type="submit">
Submit
</button>
</form>
</div>
);
}
};

It seems the crux of your question is about the code duplication between your parent component and a modal. What I would really suggest here is to decouple the modal from any specific use case and allow any consuming parent components to pass a close handler and children components.
This keeps the state in the parent, and thus, control.
Example modal component:
const Modal = ({ onClose, show, children }) =>
show ? (
<div className="modal" id="modal">
<button type="button" onClick={onClose}>
X
</button>
{children}
</div>
) : null;
Parent:
function App() {
const [isShowModal, setIsShowModal] = useState(false);
const [firstName, setFirstName] = useState();
const [lastName, setLastName] = useState();
const showModal = (e) => {
setIsShowModal((show) => !show);
};
const closeModal = () => setIsShowModal(false);
const onFormSubmit = (e) => {
e.preventDefault();
const firstName = e.target.firstName.value;
const lastName = e.target.lastName.value;
setFirstName(firstName);
setLastName(lastName);
e.target.reset();
closeModal();
};
return (
<div className="App">
<h2>First Name is : {firstName}</h2>
<h2>Last Name is : {lastName}</h2>
<button className="toggle-button" onClick={showModal}>
Show Modal
</button>
<Modal show={isShowModal} onClose={closeModal}>
<form onSubmit={onFormSubmit}>
<input type="text" name="firstName" />
<input type="text" name="lastName" />
<button className="toggle-button" type="submit">
Submit
</button>
</form>
</Modal>
</div>
);
}

Here it's really up to you how you want to manage the interaction between parent and modal content. I've shown using a form and form actions so your state isn't updated until a user submits the form. You can use form utilities (redux-form, formix, etc...) or roll your own management. Life's a garden, dig it.