I have a state with a object array. This object array is looped to render number of textboxes in the page. When I type in a textbox (after one key press), focus is removed from the textbox. Then I need to click on the textbox again to type..
I believe the issue is that in my reducer I create a new state(newArray) and return it. Due to the re-render of the newArray, mouse cursor focus is removed. I need to improve this code. How can I update the state and keep the focus on the textbox ? (Please note that reducer has many more fields inside of it and I don't want to use Redux)
const reducer = (state, action) => {
switch (action.type) {
case 'taskUpdate': {
const index = state.tasks.findIndex(task => task.id == action.payload.id);
const newArray = [...state.tasks];
newArray[index].task = action.payload.task;
newArray[index].startDate = action.payload.startDate;
newArray[index].endDate = action.payload.endDate;
return {
...state,
tasks: newArray,
}
};
default:
throw new Error();
}
};
const TenderCreate = () => {
const [state, dispatch] = useReducer(reducer, {
tasks: [{ id: 1,
task: '',
errorTask:'',
startDate: '',
errorStartDateTime:'',
endDate:'',
errorEndDateTime: ''
},
]
});
const TaskRow = ({ data }) => (
<Form.Group as={Row} controlId="task1" className="mb-3" >
<Form.Control
type="text"
placeholder=""
name="task"
className={data.errorTask ? 'is-invalid' : ''}
value={data.task}
onChange={e => {
dispatch({
type: 'taskUpdate',
payload: {
id: data.id,
task: e.target.value,
startDate: data.startDate,
endDate: data.endDate
}
});
}}
/>
</Form.Group>
);
return (
<div>
{state.tasks.map(task => (
<TaskRow data={task} key={task.id} />
))}
</div>
);
}
Reproduced issue can be viewed here → https://stackblitz.com/edit/react-ts-dudppa?file=App.tsx