Within my AddNameModal component, I am attempting to store the data URL obtained from my signature canvas into a state variable called signatureImage
It’s worth noting that AddNameModal is a component nested within another component called ModalWithForm. In ModalWithForm, I’m using the use state hook with [Image, setSignatureImage]
and providing React children (specifically, AddNameModal) with the props onChange
and signatureData
.
Here is the code for ModalWithForm:
const ModalWithForm = ({
children,
name,
onClose,
title,
button Text = "Save",
}) => {
const [formData, setFormData] = use State({});
const [signatureImage, setSignatureImage] = useState(null);
const handleSignatureCapture = (data) => {
setSignatureImage(data);
};
const handleInputChange = (e) => {
const { name, value } = e.target;
setFormData({
...formData,
[name]: value,
});
};
const onSignatureCapture = (signatureData) => {
console.log("Signature Captured:", signatureData);
setSignatureImage()
};
const childrenWithProps = React.Children.map(children, (child) => {
if (React.isValidElement(child)) {
return React.cloneElement(child, {
onChange: handleInputChange,
signatureData: onSignatureCapture,
});
}
return child;
});
const handleSubmit = (e) => {
e.preventDefault();
const finalFormData = {
...formData,
signature: signatureImage,
};
console.log("Form Data", finalFormData);
};
return (
<div className={`modal modal_type_${name}`}>
<div className="modal__content">
<button
type="button"
onClick={onClose}
className="modal__close-button"
/>
<h3 className="font-['SourceSeriff'] font-bold text-[44px] mt-[26px] text-center pb-[40px]">
{title}
</h3>
<form onSubmit={handleSubmit}>
{childrenWithProps}
<div className="flex justify-end">
<button type="submit" className="modal__submit-button">
{buttonText}
</button>
</div>
</form>
</div>
</div>
);
};
Here is the code for AddNameModal component:
const AddNameModal = ({ onClose,signatureData, onSignatureCapture }) => {
console.log(signatureData)
const sigCanvasRef = React.createRef();
const handleClear = () => {
sigCanvasRef.current.clear();
};
const handleSaveSignature = (signatureData) => {
signatureData = sigCanvasRef.current.getTrimmedCanvas().toDataURL("image/png");
console.log(signatureData)
onSignatureCapture
};
return (
<ModalWithForm
onClose={onClose}
name="add-name"
title="Policy Agreement Signature"
>
<div className="modal__form-contents">
<label>
<p className=" text-2xl font-['SourceSerif'] mb-[10px] font-[700]">
First Name
</p>
<input
className="border-black border-2 border-solid w-full rounded p-[5px] mb-[10px]"
type="text"
name="firstname"
minLength="4"
maxLength="15"
placeholder="first"
required
/>
<span className="modal__error"></span>
</label>
<label>
<p className=" text-2xl font-['SourceSerif'] mb-[10px] font-[700]">
Last Name
</p>
<input
className="border-black border-2 border-solid w-full rounded p-[5px] mb-[10px]"
type="text"
name="lastname"
minLength="4"
maxLength="15"
placeholder="last"
required
/>
<span className="modal__error"></span>
</label>
<div className="mt-[10px] mb-[20px] ">
<p className={`modal__input-title mb-[15px]`}>Signature</p>
<div className="w-[100%] h-[200px] border-solid border-2 border-black">
<SignatureCanvas
ref={sigCanvasRef}
penColor="black"
canvasProps={{
className: "signature-canvas",
}}
/>
</div>
<span></span>
<button
className="signature__clear-button"
onClick={handleClear}
type="button"
>
Clear Signature
</button>
<button className="signature__save-button" onClick={handleSaveSignature} type="button">
Save Signature
</button>
</div>
</div>
</ModalWithForm>
);
};
I tried different approaches this is why the code might be a little jumbled up. I just will like a point in the right direction. What I expect is for me to beable to send the data URl from the signatureCanvas upwards to the parent component and then onSubmit send this data through a Api request.
2
Answers
Usually in React the data flows from top level component to low level component. What you can try to do is declare
const [signatureImage, setSignatureImage] = useState(null)
state hook at the parent component and then pass it down asprops
into your children component.What you would do is you will make a useState for storing the data URl from the signatureCanvas and pass the set function of that useState to the child component i.e(AddNameModal component). Upon getting the signatureData you will use the setFunction you just passed from the parent component to set the state with that signatureData.
Now you’ll probably be asking how would the parent component come to know when to call the API request once we have that signatureData in our state? For that you will make a useEffect hook with a dependency of state that we made to hold sinatureData and inside the useEffect you will call the function which as you said to send this data through API request.
when you are done with this, as soon as your child components gets the desired signatureData your Api request will be called with that signatureData.