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).
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With