Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React text input loses focus when I type a letter

Tags:

reactjs

I have an text input field that is a controlled React component. When I type a letter into the field, the input loses focus and the cursor disappears. The file in question is /src/modules/PollName.js.

https://codesandbox.io/embed/wkl1kkp0pk?fontsize=14

I have tried moving the component (InputText) outside of the rendering function (PollTable), and passing a handler function as a prop to the input so it can update state, which lives inside the render function. This is the advice I was reading on other posts, but this doesn't seem to be working, either.

If you look on the browser example, and click inside of the form input called Poll Name and type a letter, you'll see that the cursor disappears after typing.

import React, { useState, useReducer } from 'react';
import { pollTable, sorting, filter } from './../helpers/Fetch';

function InputText(props) {
  return(
    <div className="polls-filter__inputs-row">
      <label className="polls-filter__input-label" htmlFor={props.name}>{props.label}</label>
      <input
        type="text"
        id={props.name}
        name={props.name}
        value={props.value}
        onChange={props.handleOnChange}
      />
    </div>
  )
}

function PollTable() {
  const [tableData, setTableData] = useReducer(
    dataReducer,
    pollTable,
    dataInit
  );

  function dataInit(pollTable) {
    return {
      data: sorting(pollTable, `pollName`, true),
      sortBy: {
        column: `pollName`,
        asc: true
      },
      filteredBy: {
        pollName: ``,
        author: ``,
        affiliates: [],
        status: ``
      }
    }
  }

  function dataReducer(state, action) {
    const stateFilters = state.filteredBy;
    let dataResult = state.data;
    let column = (action.sortBy && action.sortBy.column) || state.sortBy.column;
    let asc;
    if (action.sortBy) {
      asc = state.sortBy.column === action.sortBy.column ? !state.sortBy.asc : true;
    } else {
      asc = state.sortBy.asc;
    }
    // Filter through results
    if (action.filterBy) {
      stateFilters[action.filterBy.column] = action.filterBy.value;
      dataResult = filter(dataResult, stateFilters);
    }
    // Pass results into state
    return {
      data: sorting(dataResult, column, asc),
      sortBy: {
        column: column,
        asc: asc
      },
      filteredBy: stateFilters
    }
  }

  function handleOnChange(e) {
    setTableData({
      filterBy: {
        column: e.target.name.replace(`filter-`, ``),
        value: e.target.value
      }
    })
  }

  function FilterInputsRow(props) {
    if (props.type === `text`) {
      return(
        <InputText
          name={props.name}
          label={props.label}
          filterByColumn={props.filterByColumn}
          value={props.value}
          handleOnChange={props.handleOnChange}
        />
      )
    }
  }

  function FilterInputs() {
    // Changes the class on the main filter dropdown div to open/close the dropdown
    const setClassName = !openFilters ? `polls-filter__inputs` : `polls-filter__inputs polls-filter__inputs--show`;
    return(
      <form className={setClassName} key="filter-form">
        <FilterInputsRow
          type="text"
          name="filter-pollName"
          label="Poll Name"
          filterByColumn="pollName"
          value={tableData.filteredBy.pollName}
          handleOnChange={handleOnChange}
        />
      </form>
    )
  }

  return(
    <div className="polls-filter">
      <Filter />
      <FilterInputs />
    </div>
  )
}

export default PollTable;

I expect for the input to remain in focus so as the user types in the field, it filters the results in a table (not shown here).

like image 481
Barry Horbal Avatar asked May 09 '19 17:05

Barry Horbal


1 Answers

The main problem you have is that you define your components inside another component. Your components are redefined on every render of PollTable component. Move functions definition out of PollTable component and everything will work.

Here I have edited your code: https://codesandbox.io/s/14427lzmo7

Note, that if you define some functions inside a component this could cause bugs and reduce the performance of your app.

like image 57
Andrii Golubenko Avatar answered Oct 19 '22 01:10

Andrii Golubenko