React Forms, Controlled Components, Validation | Sinhala Guide

ආයුබෝවන් React Dev යාළුවනේ! React Forms සහ Controlled Components පහසුවෙන් ඉගෙන ගනිමු
ආයුබෝවන් යාළුවනේ! React එක්ක වැඩ කරනකොට Forms කියන්නේ ටිකක් අවුල් සහගත මාතෘකාවක් කියලා හිතෙනවද? නැත්තම් කොහොමද User ගෙන් ගන්න Input Data හරියට Manage කරන්නේ කියලා ප්රශ්නයක්ද? එහෙනම් මේ Tutorial එක ඔයාට තමයි! වෙබ් Application එකක් හදනකොට User ගෙන් Data ගන්න Forms කියන්නේ අනිවාර්ය දෙයක්. User Registration, Login, Contact Forms වගේ දේවල් වලට මේ Forms අත්යවශ්යයි.
මේ Guide එකෙන් අපි ReactJS Forms ගැන මුල සිට සරලව කතා කරනවා. විශේෂයෙන්ම Controlled Components කියන්නේ මොකක්ද, ඒවා පාවිච්චි කරන්නේ කොහොමද, State Management කරන්නේ කොහොමද, වගේම Input Validation එකක් කොහොමද කරන්නෙ කියලත් අපි ඉගෙන ගන්නවා. තවදුරටත්, අපි සරල Registration Form එකක් හදලා මේ හැම දෙයක්ම Practical විදිහට බලමු. මොකද මේක React Developer කෙනෙක් විදිහට ඔයාට අනිවාර්යයෙන්ම දැනගන්න ඕන දෙයක්!
1. Forms in React – මූලික කරුණු (The Basics)
සාමාන්ය HTML වලදී අපි Form එකක් හදන්නේ මෙහෙමයි:
<form>
<label for="name">නම:</label>
<input type="text" id="name" name="userName" />
<button type="submit">Submit</button>
</form>
මේ වගේ Form එකක් Submit කරාම, Page එක Refresh වෙලා, Server එකට Data යනවා. නමුත් React වලදී අපි කැමති නැහැ හැම වෙලාවෙම Page එක Refresh වෙනවට. අපි කැමතියි User Input එක Real-time විදිහට Manage කරන්න, ඒ අනුව UI එක Update කරන්න.
React වලදී Forms වල Data හසුරුවන ප්රධාන ක්රම දෙකක් තියෙනවා: Controlled Components සහ Uncontrolled Components. මේ දෙකෙන් අපි බොහෝ වෙලාවට පාවිච්චි කරන්නේ Controlled Components. ඒ ඇයි කියලත් අපි බලමු.
2. Controlled Components – React ක්රමය
Controlled Component එකක් කියන්නේ, ඒ input
element එකේ value
එක React state එකකින් control කරන එක. ඒ කියන්නේ, input
box එකක තියෙන දත්ත (value) මොකක්ද කියලා තීරණය කරන්නේ React Component එකේ state එකෙන්. User කෙනෙක් input
එකට මොනවා හරි type කරන හැම වෙලාවෙම, ඒ value
එක React state එකට Update වෙනවා.
වැදගත් ගුණාංග දෙක: value
සහ onChange
value
: මේprop
එකෙන්input
එකේ වත්මන් අගය තීරණය කරනවා. මේක හැම වෙලාවෙම state එකෙන් එන්න ඕනේ.onChange
: මේevent handler
එක trigger වෙන්නේ User කෙනෙක්input
එකකvalue
එක වෙනස් කරන හැම වෙලාවෙම. මේකෙන් තමයි අපි state එක Update කරන්නේ.
සරල උදාහරණයක් බලමු:
import React, { useState } from 'react';
function NameInput() {
const [name, setName] = useState(''); // State එකක් හදාගන්නවා
const handleChange = (event) => {
setName(event.target.value); // Input value එකෙන් state එක Update කරනවා
};
return (
<div>
<label htmlFor="name">ඔබේ නම:</label>
<input
type="text"
id="name"
value={name} // Input එකේ value එක state එකෙන් control කරනවා
onChange={handleChange} // onChange event එක handle කරනවා
/>
<p>ආයුබෝවන්, <strong>{name}</strong>!</p>
</div>
);
}
export default NameInput;
මේ Code එකෙන් වෙන්නේ:
useState('')
මගින්name
කියන state variable එකක් හදාගන්නවා, මුලින් හිස් string එකක් විදිහට.<input>
එකේvalue={name}
කියල දානවා, ඒ කියන්නේinput
එකේ වත්මන් අගය හැමවෙලාවෙමname
state එකේ තියෙන අගයයි.onChange={handleChange}
මගින් කියන්නේinput
එකට මොනවා හරි type කරාමhandleChange
function එක ක්රියාත්මක වෙන්න ඕනේ කියලා.handleChange
function එක ඇතුලේsetName(event.target.value)
මගින්input
එකේ අලුත් අගයname
state එකට දානවා.
මේ ක්රමයෙන් input
එකේ තියෙන හැම අකුරක්ම අපේ React state එකේ තියෙන නිසා, අපිට ඒ value
එක ඕන වෙලාවක පාවිච්චි කරන්න, වෙනස් කරන්න, හෝ validate කරන්න පුළුවන්.
3. සරල Registration Form එකක් සහ Validation
දැන් අපි මේ දැනුම පාවිච්චි කරලා සරල Registration Form එකක් හදමු. මේ Form එකේ නම (Name), ඊමේල් (Email), සහ මුරපදය (Password) කියන fields තුන තියෙනවා. ඒ වගේම අපි Input Validation එකකුත් එකතු කරමු.
import React, { useState } from 'react';
function RegistrationForm() {
// State එකක් හදනවා හැම input field එකකම values ටික තියාගන්න
const [formData, setFormData] = useState({
name: '',
email: '',
password: '',
});
// State එකක් හදනවා validation errors ටික තියාගන්න
const [errors, setErrors] = useState({});
// Input changes handle කරන function එක
const handleChange = (event) => {
const { name, value } = event.target;
setFormData((prevFormData) => ({ ...prevFormData, [name]: value }));
};
// Validation කරන function එක
const validateForm = () => {
const newErrors = {};
if (!formData.name.trim()) {
newErrors.name = 'නම ඇතුළත් කරන්න.';
} else if (formData.name.length < 3) {
newErrors.name = 'නම අකුරු 3කට වඩා දිග විය යුතුයි.';
}
if (!formData.email.trim()) {
newErrors.email = 'ඊමේල් ලිපිනය ඇතුළත් කරන්න.';
} else if (!/^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/.test(formData.email)) {
newErrors.email = 'වලංගු ඊමේල් ලිපිනයක් ඇතුළත් කරන්න.';
}
if (!formData.password.trim()) {
newErrors.password = 'මුරපදයක් ඇතුළත් කරන්න.';
} else if (formData.password.length < 6) {
newErrors.password = 'මුරපදය අකුරු 6කට වඩා දිග විය යුතුයි.';
}
setErrors(newErrors);
return Object.keys(newErrors).length === 0; // Errors නැත්නම් true return කරනවා
};
// Form submit කරන function එක
const handleSubmit = (event) => {
event.preventDefault(); // Default form submission එක නවත්වනවා
if (validateForm()) {
// Validation සාර්ථක නම් මෙතනින් data process කරන්න පුළුවන්
console.log('Form Submitted Successfully:', formData);
alert(`Registration Successful for ${formData.name}!`);
// Form එක reset කරන්න ඕනිනම්:
// setFormData({ name: '', email: '', password: '' });
} else {
console.log('Form has errors.');
}
};
return (
<div style={{ maxWidth: '400px', margin: '20px auto', padding: '20px', border: '1px solid #ccc', borderRadius: '8px' }}>
<h2>අලුත් ගිණුමක් සාදන්න</h2>
<form onSubmit={handleSubmit}>
<div style={{ marginBottom: '15px' }}>
<label htmlFor="name" style={{ display: 'block', marginBottom: '5px' }}>නම:</label>
<input
type="text"
id="name"
name="name"
value={formData.name}
onChange={handleChange}
style={{ width: '100%', padding: '8px', boxSizing: 'border-box', border: errors.name ? '1px solid red' : '1px solid #ddd' }}
/>
{errors.name && <p style={{ color: 'red', fontSize: '0.9em', marginTop: '5px' }}>{errors.name}</p>}
</div>
<div style={{ marginBottom: '15px' }}>
<label htmlFor="email" style={{ display: 'block', marginBottom: '5px' }}>ඊමේල් ලිපිනය:</label>
<input
type="email"
id="email"
name="email"
value={formData.email}
onChange={handleChange}
style={{ width: '100%', padding: '8px', boxSizing: 'border-box', border: errors.email ? '1px solid red' : '1px solid #ddd' }}
/>
{errors.email && <p style={{ color: 'red', fontSize: '0.9em', marginTop: '5px' }}>{errors.email}</p>}
</div>
<div style={{ marginBottom: '20px' }}>
<label htmlFor="password" style={{ display: 'block', marginBottom: '5px' }}>මුරපදය:</label>
<input
type="password"
id="password"
name="password"
value={formData.password}
onChange={handleChange}
style={{ width: '100%', padding: '8px', boxSizing: 'border-box', border: errors.password ? '1px solid red' : '1px solid #ddd' }}
/>
{errors.password && <p style={{ color: 'red', fontSize: '0.9em', marginTop: '5px' }}>{errors.password}</p>}
</div>
<button type="submit"
style={{
width: '100%',
padding: '10px 15px',
backgroundColor: '#007bff',
color: 'white',
border: 'none',
borderRadius: '4px',
cursor: 'pointer',
fontSize: '1em'
}}
>ගිණුමක් සාදන්න</button>
</form>
</div>
);
}
export default RegistrationForm;
මේ Code එකෙන් වෙන්නේ මොකක්ද?
- Multiple Inputs සඳහා Single State Object එකක්: අපි
useState
පාවිච්චි කරලාformData
කියනobject
එකක් හදාගන්නවා. මේක ඇතුළේ Form එකේ හැමinput
එකකමvalue
එකkey-value
යුගලයක් විදිහට තියාගන්නවා (name: '', email: '', password: ''
). - Generic
handleChange
Function එකක්:handleChange
function එක ඇතුලේevent.target.name
සහevent.target.value
පාවිච්චි කරලා,event
එක trigger වුණුinput
එකේname
එක අනුව අදාළkey
එකේvalue
එක Update කරනවා....prevFormData
මගින් කලින් තිබ්බformData
එකේ අගයන් එලෙසම තියාගෙන, වෙනස් වුණුinput
එකේ අගය විතරක් overwrite කරනවා. - Validation:
validateForm
කියන function එකෙන් Form එකේ fields ටික validate කරනවා. හිස්ද, ඊමේල් format එක හරිද, password එකේ දිග ප්රමාණවත්ද වගේ දේවල් බලනවා. Errors තියෙනවා නම්,setErrors
මගින්errors
state එකට ඒ Errors ටික එකතු කරනවා. - Error Messages Display කිරීම:
{errors.name && <p>{errors.name}</p>}
වගේ Conditional Rendering පාවිච්චි කරලා Errors තියෙනවා නම් ඒinput
එක යටින් Error Message එක පෙන්නනවා. - Form Submission Handling:
<form>
එකටonSubmit={handleSubmit}
දාලා Form එක Submit කරනකොටhandleSubmit
function එක ක්රියාත්මක කරනවා. මේක ඇතුලේevent.preventDefault()
දාලා Default Browser Behavior එක (Page Refresh වෙන එක) නවත්වනවා. ඊට පස්සේvalidateForm()
එක Call කරලා Form එක validate කරලා, හැම දෙයක්ම හරි නම් Data ටිකconsole.log
කරනවා.
4. Uncontrolled Components – කවදාද, ඇයි?
Uncontrolled Components කියන්නේ, HTML Form elements වල Data හසුරුවන්න React state එකක් පාවිච්චි නොකරන input
elements. මේවා සාමාන්ය HTML Form elements වගේම ක්රියා කරනවා. මේවායේ Data ගන්න අපි useRef
Hook එක පාවිච්චි කරනවා.
උදාහරණයක්:
import React, { useRef } from 'react';
function UncontrolledForm() {
const nameInputRef = useRef(null);
const handleSubmit = (event) => {
event.preventDefault();
alert(`User Name: ${nameInputRef.current.value}`);
};
return (
<form onSubmit={handleSubmit}>
<label>නම:</label>
<input type="text" ref={nameInputRef} />
<button type="submit">Submit</button>
</form>
);
}
export default UncontrolledForm;
කවදාද පාවිච්චි කරන්නේ?
- Simple Forms: ඉතාම සරල Forms වලදී.
- File Inputs:
<input type="file" />
වගේ Components වලvalue
එක Programmatically set කරන්න බැරි නිසා. - Third-party DOM Libraries: React නොවන JavaScript Libraries එක්ක Integrate කරනකොට.
නමුත්, බොහෝ විට Controlled Components පාවිච්චි කරන්න කියලා තමයි React Recommend කරන්නේ. මොකද Controlled Components මගින් Form Data, State එකත් එක්ක Sync වෙලා තියෙන නිසා, Debug කරන්න, Validate කරන්න, සහ Data Flow එක Manage කරන්න පහසුයි.
5. හොඳම ක්රම සහ පොදු ගැටළු (Best Practices & Common Troubleshooting)
හොඳම ක්රම (Best Practices)
- හැමවිටම Controlled Components පාවිච්චි කරන්න: Predictable Behavior සහ පහසු Data Management නිසා මේවා තමයි හොඳම විකල්පය.
- Lift State Up: Form එකේ Data එක Components කිහිපයකට අවශ්ය නම්, Parent Component එකක State එක තියාගෙන
props
හරහා Data එක Share කරන්න. - Validation Logic වෙන් කරන්න: Validation Logic එක වෙනම Function එකක් විදිහට හරි, Custom Hook එකක් විදිහට හරි තියාගන්න.
- Third-Party Libraries: Form Handling Libraries (e.g., Formik, React Hook Form, Yup for validation) පාවිච්චි කරන්න පුළුවන්. මේවා Form handling process එක තවත් පහසු කරනවා.
පොදු ගැටළු සහ විසඳුම් (Common Troubleshooting)
- Input එකට Type කරද්දී Update වෙන්නේ නැහැ! (Input Not Updating)
- ගැටළුව:
input
එකේvalue
prop
එකටstate
එකක් දීලා, ඒත්onChange
event handler
එක දාලා නැත්තම්, නැත්තම්onChange
එකෙන්state
එක Update කරන්නේ නැත්නම්input
එකට Type කරන්න බැරි වෙනවා. මොකදvalue
එක හැමවෙලාවෙමstate
එකෙන් එන නිසා. - විසඳුම:
onChange
prop
එක අනිවාර්යයෙන් දාලා, ඒක ඇතුළතevent.target.value
එකෙන්state
එක Update කරන්න.
- ගැටළුව:
- State Updates ක්ෂණිකව 반영 වෙන්නේ නැහැ! (State Updates Not Reflecting Immediately)
- ගැටළුව:
setState
Function එක asynchronous නිසා, සමහර වෙලාවටsetState
Call කරපු ගමන්ම ඊළඟ Line එකේදී අලුත්state value
එක බලාපොරොත්තු වෙන්න බැහැ. - විසඳුම:
state
එක Update වුනාට පස්සේ මොනවා හරි කරන්න ඕනි නම්,useEffect
Hook එක පාවිච්චි කරන්න පුළුවන්.
- ගැටළුව:
const [count, setCount] = useState(0);
const handleClick = () => {
setCount(count + 1);
// මෙතනදී count එකේ අලුත් value එක ලැබෙන්නේ නැහැ, කලින් value එක තමයි තියෙන්නේ.
console.log(count); // Output කරන්නේ update වීමට පෙර තිබූ count අගයයි.
};
// count state එක වෙනස් වෙනකොට මේ effect එක run වෙනවා.
useEffect(() => {
console.log('Count updated to:', count);
}, [count]);
// වැරදි
<input type="text" value={name} />
// නිවැරදි
<input type="text" value={name} onChange={(e) => setName(e.target.value)} />
අවසන් වචනය (Conclusion)
React Forms සහ Controlled Components කියන්නේ React Development වලදී අත්යාවශ්යම Concept එකක්. අද අපි මේ Guide එකෙන් Forms වල මූලික කරුණු, Controlled Components කියන්නේ මොකක්ද, ඒවා කොහොමද පාවිච්චි කරන්නේ, වගේම Input Validation එකක් කොහොමද කරන්නේ කියලත් ඉගෙන ගත්තා. අපි හදපු Registration Form එක ඔයාට හොඳ ආරම්භයක් වෙයි කියලා මම හිතනවා.
මේ Concept එක හොඳට තේරුම් ගන්න නම්, අනිවාර්යයෙන්ම Code එක Try කරලා බලන්න. ඔයාගේම Form එකක් හදලා විවිධ Validation Rules එකතු කරලා බලන්න. මොනවා හරි ප්රශ්න තියෙනවා නම්, පහලින් Comment එකක් දාන්න. අපි ඒ ගැන කතා කරමු! ඔයාගේ React Journey එකට සුභ පැතුම්!