In my react.js ponent, input field is lose focus whenever a character is typed and need to click on the input field again to type or edit the next character. Why's this happening?
Here is my code :
// State to store DataSource
const [dataSource, setDataSource] = useState<any>(data);
const handleOnchange = (event: any, props: any) => {
const newData = [...dataSource];
const itemIndex = newData.findIndex(
(item) => item.OrderID === props.OrderID
);
newData[itemIndex].Freight = event.target.value;
setDataSource(newData);
};
// Custom Grid Component
const gridTemplate = (props: any) => {
const val = props.Freight;
return (
<div>
<input value={val} onChange={(event) => handleOnchange(event, props)} />
</div>
);
};
I've already tried changing onChange
to onBlur
, but no help!
Thanks
In my react.js ponent, input field is lose focus whenever a character is typed and need to click on the input field again to type or edit the next character. Why's this happening?
Here is my code :
// State to store DataSource
const [dataSource, setDataSource] = useState<any>(data);
const handleOnchange = (event: any, props: any) => {
const newData = [...dataSource];
const itemIndex = newData.findIndex(
(item) => item.OrderID === props.OrderID
);
newData[itemIndex].Freight = event.target.value;
setDataSource(newData);
};
// Custom Grid Component
const gridTemplate = (props: any) => {
const val = props.Freight;
return (
<div>
<input value={val} onChange={(event) => handleOnchange(event, props)} />
</div>
);
};
I've already tried changing onChange
to onBlur
, but no help!
Thanks
Share Improve this question edited May 12, 2023 at 10:28 Anandhu Remanan asked May 12, 2023 at 10:13 Anandhu RemananAnandhu Remanan 1132 silver badges10 bronze badges 4- lots of previous questions covering this topic, have the checked those answers? stackoverflow./questions/22573494/… stackoverflow./questions/42573017/… stackoverflow./questions/42573017/… – Toby Hamand Commented May 12, 2023 at 10:33
- I tried to replicate your ponent, there are a couple of things I didn't get. Why are you saving an array inside an input ponent? Could you please provide a working example on stackblitz? – noviceGuru Commented May 12, 2023 at 10:35
- Hi @Toby Hamand, thanks for your reply I've tried almost all of them and still struggling to find a solution. – Anandhu Remanan Commented May 12, 2023 at 10:49
- Hi @noviceGuru, thanks for your reply, Here is the link for the working sample on stackblitz: stackblitz./edit/react-ts-ggqwch?file=App.tsx . I'm trying to update a syncfusion Grid. – Anandhu Remanan Commented May 12, 2023 at 11:13
3 Answers
Reset to default 2If the value prop is constantly updated with each keystroke, it causes the input field to lose focus because the ponent is being re-rendered.
You need to separate the value of the input field from the state and only update the state when necessary.
If I understand correctly gridTemplate
is a ponent created inside another ponent.
The rule is: never ever create ponent inside another ponent if it is not necessary to do that. If it is required to do that, use useCallback. Move the inner ponent gridTemplate
outside of your ponent and pass the things it require as props
On each render it gets new reference and React thinks it is new ponent and unmounts the previuos one and mounts the new one
By looking at the Stackblitz you shared it seems like you're not integrating Syncfusion right, they don't allow you to have controlled inputs in their templates because of their internal rendering logic.
Instead you should setup an event listener using a reference to the grid to listen to changes (keyup
) on grid elements and retrieve the changes (input value). Since the input will be uncontrolled (you're only passing a defaultValue
and you don't control what its current value will be) you won't have to update its value since it will be updated already (last thing the user typed).
I adapted the following code from their docs on edition to give you an idea on how to set it up:
function App() {
const grid = React.useRef<any>() // Keep a reference to the grid, we'll use it in the created function.
const gridTemplate = (props: any) => { // Similar gridTemplate function but just sets a default value and doesn't attach a React event handler, that will be handled on grid creation.
return (<div>
<input id={props.OrderID} defaultValue={props.Freight} className='custemp' type='text'/>
</div>);
};
const created = (args: any) => { // This function will be run by Syncfusion on creation
grid.current.element.addEventListener('keyup', function (e: any) {
if (e.target.classList.contains('custemp')) { // Based on condition, you can find whether the target is an input element or not.
let row = parentsUntil(e.target, 'e-row');
let rowIndex = row.rowIndex; // Get the row index.
let uid = row.getAttribute('data-uid');
let grid = document.getElementsByClassName('e-grid')[0].ej2_instances[0];
let rowData = grid.getRowObjectFromUID(uid).data; // Get the row data.
rowData.Freight = e.target.value; // Update the new value for the corresponding column.
grid.current.updateRow(rowIndex, rowData); // Update the modified value in the row data.
}
});
};
return <GridComponent dataSource={data} ref={g => gridRef.current = g} height={315} created={created}>
<ColumnsDirective>
<ColumnDirective field='OrderID' headerText='Order ID' width='120' textAlign="Right" isPrimaryKey={true}/>
<ColumnDirective field='OrderDate' headerText='Order Date' width='130' textAlign="Right" format='yMd'/>
<ColumnDirective field='ShipCountry' headerText='Ship Country' width='140'/>
<ColumnDirective field='Freight' headerText='Receipt Amount' width='140' template={gridTemplate}/>
</ColumnsDirective>
</GridComponent>;
}
The code was originally written in plain Javascript.
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745355270a4624077.html
评论列表(0条)