const handleChange = (e, id, property) => {
const { value } = e.target;
const fieldIndex = InputformData.findIndex((field) => field.id === id);
if (fieldIndex !== -1) {
const updatedInputformData = [...InputformData];
updatedInputformData[fieldIndex] = {
...updatedInputformData[fieldIndex],
[property]: value,
};
setInputFormData(updatedInputformData);
}
};
#help implementing debounce for my function
63 messages ยท Page 1 of 1 (latest)
i have 66 records of input fields and they all have a onChange , i need to implment debounce for this
here is the updted code
const handleChange = (e, id, property) => {
const { value } = e.target;
setInputFormData((prevInputFormData) => {
return prevInputFormData.map((field) => {
if (field.id === id) {
return {
...field,
[property]: value,
};
}
return field;
});
});
};
Would you be able to share the data model you use?
Are you rendering the inputs based on that data?
yea basically a pdf is submitted , my api generates the form fields of it, and iam showing them on the frontend amd basically changing their label, data type and field type sort of stuff
cant send the modal, its confidential , i can show you the frontend
It could become cumbersome if you want to create a good debounce hook so I would recommend you to try out the following package:
https://github.com/xnimorz/use-debounce
to be honest you might need lodas debounce instead:
https://www.npmjs.com/package/lodash.debounce
I've made an example if you are curious:
https://codesandbox.io/p/sandbox/debounce-input-react-example-h9d3fw?file=%2Fsrc%2FApp.tsx%3A43%2C31
Even the root functions can be memoized using useCallback or useMemo if necessary but I wouldn't worry about it if performance is not very poor
You can try to implement your own debounce function, it is not super hard but it would be easier to use something that's "on the market" for a long time and well maintained
const handleChange = useCallback(
(e, id, property) => {
const { type, value, checked } = e.target;
setFormFields((prevFormFields) => {
return prevFormFields.map((field) => {
if (field.id === id) {
if (type === "checkbox") {
return {
...field,
[property]: checked,
};
} else {
return {
...field,
[property]: value,
};
}
}
return field;
});
});
},
[formFields]
);
const debouncedFunc = debounce((e,id,property) => handleChange(e,id,property),1000)
its not working now
tried debounce.lodash
let me take a loomk at it later, rn iam off from job and have to sleep rn
bence you there
hey, what's up?
i will catch you in a moment
why did you use a set here , and why filtering with key
iam just trying to understand your code
debounce is working but iam not able to type in the field now, i have added a 5 second delay , its working fine
but the thing is my onChange is not even trackin the values
@near meadow sorry for the ping , but iam stuck cant find much on documentation tho
oh, I just didn't want to allow people to update the id and I didn't know what your data model is so I just made something up.
That set only to filter out the visible fields to the user. It is not relevant to the debouncing.
What function have you used the debounce on?
Could you share your change handler?
const handleChange = useCallback(
debounce((e, id, property) => {
const { type, value, checked } = e.target;
console.log(value)
setFormFields((prevFormFields) => {
return prevFormFields.map((field) => {
if (field.id === id) {
if (type === "checkbox") {
return {
...field,
[property]: checked,
};
} else {
return {
...field,
[property]: value,
};
}
}
return field;
});
});
}, 400),
[formFields]
);
this is the onChange handler
<TextField
label="Label"
name="label"
placeholder={"label"}
value={label}
onChange={(e) => handleChange(e, id,"label")}
/>
<TextField
select
label="DataType"
name="dataType"
defaultValue={"text"}
placeholder={"dataType"}
value={dataType}
sx={{ width: "30%" }}
onChange={(e) => handleChange(e, id,"dataType")}
>
{dataTypeOptions?.map((type) => {
return (
<MenuItem key={type.value} value={type.value}>
{type.label}
</MenuItem>
);
})}
</TextField>
<TextField
disabled={true}
label="FieldType"
name="fieldType"
placeholder={"fieldType"}
value={fieldType}
onChange={(e) => handleChange(e, id,"fieldType")}
/>
and utilization of onChange
you don't need formFields as a dependency of useCallback
I believe the problem here is the value property on the TextField
You need to use defaultValue or defaultCheck otherwise the input is controlled and you won't be able use debounce on it I think
so i should set the values of all fields as default values
like
defaultValue={fieldType}
defaultValue={dataType}
so then i will need to desstructure the default value from event, i dont know if i can
yes. Unless that is problematic
no, you just grab the value like before
the defaultValue will be the value of the input at render time
The input has its internal state and the defaultValue is basically the initial value of the input.
you are a life saver bence! thank you so much
it works perfectly okay now
nice! ๐ ๐
i need to deep dive into controlled vs uncontrolled componnets
There is not much to know about them, react doc covers it as far as I remember.
There are plenty of resources regarding this subject on YT as well.
Your problem wasn't trivial. ๐
i was worried all day, today is my deadline to submit this task lol
cant thank you enough! ๐ธ
I'm glad we found a solution ๐
Do you have to use debounce to optimize this component?
Do you think there is another way of optimizing it?
I think debouncing just do fine
do you have any idea of further enhancing this component, first i thought i can also paginate the responses, but cant really do that, iam extracting all the pdf form fields which are actually fillable, thet told me to extract all the fields of it, and then update their labels,datatype etc..!
so i want all the response , paginate is not applicable here
if the pdf has 100s of fields it will dynamically extract and fetch those, making this doing heavy lifting for updating data
i might memoize the jsx with useMemo
not necessarily debounce, Before debouncing there was so much lag when i started filling out fields, react reacts to every single keystroke change , making it unresponsive to handle such large data without using optimization
Yes, as you have controlled inputs, every input change will update your state, which causes react to re-render the entire tree. Creating a component which takes in primitive values then using react.memo on it would help the performance
I have an example for that scenario if you are interested: https://codesandbox.io/s/react-memo-example-e63j18
Unfortunately, without seeing the layout of the page I won't be able to give you more tips to improve performance but from what I saw React.memo is an option.
if you use react.memo, you could even have controlled inputs ๐ค
if that is a requirement (sometimes we just have to do that, business logic or otherwise)
memo only memoize the component untill the props change, you see filling the fields will definitely change the props all the time, so it react.memo would be of no use, i choose the fields component separate it takes all the fields data and populate the UI
but you have an array of field which will be rendered out. Each of them can be a memoized component. If you change an input field that will not affect the other fields in terms of performance
iam gonna update you on this
๐