So the BetterInputGroup component is re-rendering after ever letter typed, I'm still struggling to wrap my head around how React works like that and why. Is it because I'm using the BetterInputGroup component inside the AddTask component? If I move it out or to another file I lose access to the formData state and handleFormChange.
Is there a better way of doing this or am I being really dumb?
const AddTask = () => {
const [formData, setFormData] = useState({
data: {taskname: "", department: "", frequency: -1, subtasks: [{name: "", description: "", inputtype: 0, inputprefix: ""}]},
validity: {taskname: false, department: false, frequency: false, subtasks: [{name: false, inputtype: false}]}})
const BetterInputGroup = ({sidetext, styledata, pathtodata}) => {
const pathList = pathtodata.split(".")
let compValid = pathList.length > 1 ? formData["validity"][pathList[0]][pathList[1]] : formData["validity"][pathtodata]
let compValue = pathList.length > 1 ? formData["data"][pathList[0]][pathList[1]] : formData["data"][pathtodata]
return (
<CInputGroup className={styledata}>
<CInputGroupText>{sidetext}</CInputGroupText>
<CFormInput type="text" value={compValue}
onChange={e => {handleFormChange(e, pathtodata)}}
valid={compValid}
invalid={!compValid}/>
</CInputGroup>
)
}
const handleFormChange = (event, path) => {
let newFormData = {...formData}
const pathList = path.split(".")
if(pathList === "subtasks") {
newFormData["data"]["subtasks"][pathList[1]][pathList[2]] = event.target.value
if(newFormData["validity"]["subtasks"][pathList[1]][pathList[2]] != null) {
// newFormData["validity"]["subtasks"][pathList[1]][pathList[2]] = regexes["subtasks"][pathList[2]].test(event.target.value)
}
} else {
newFormData["data"][pathList[0]] = event.target.value
newFormData["validity"][pathList[0]] = regexes[pathList[0]].test(event.target.value)
}
setFormData(newFormData)
}
const regexes = {taskname: /[a-zA-Z\s]+$/, department: /[1-9]$/, frequency: /^(?:[1-9]\d?|[12]\d{2}|3[0-5]\d|36[0-5])$/, sutasks: {name: /[a-zA-Z\s]{20}$/, inputtype: /[1-9]$/}}
return (
<>
<BetterInputGroup styledata="w-auto p-3 has-validation" sidetext="Task name" pathtodata="taskname" />
</>
)
Yes, the reason why BetterInputGroup is re-rendering after every letter typed is because it is defined inside the AddTask component and is using formData and handleFormChange from the parent component's state. In React, when a state or prop changes, all child components that depend on that state or prop will re-render.
One solution to reduce the unnecessary re-renders of BetterInputGroup is to extract it as a separate component and pass the necessary props down to it. For example:
By extracting the InputGroup component, we can pass only the necessary props instead of passing the whole state object and function down as a prop. This can help reduce unnecessary re-renders of the component.