javascript - Why my Input Field lose focus after typing a single character in React.js? - Stack Overflow

In my react.js ponent, input field is lose focus whenever a character is typed and need to click on the

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
Add a ment  | 

3 Answers 3

Reset to default 2

If 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条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信