React reducer updating array of textboxes

72 views Asked by At

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

0

There are 0 answers