React-table: 6.9.2: Header Filter Input Losing Focus After Keydown

Created on 12 Feb 2019  路  13Comments  路  Source: tannerlinsley/react-table

In 6.9.2, the open field text inputs in the header columns are losing focus after you press a key. I believe this came in with the 6.9.0 changes.

As a sidenote, I replaced the regular text inputs with a search input, which is nice because you get the 'clear' button and it doesn't trigger the browser's autocomplete. Pretty sure that has nothing to do with losing focus, but I'll keep testing.

FilterComponent={({ filter, onChange, column }) => (
  <input
    className="w-100"
    type="search"
    placeholder={column.Placeholder}
    value={filter ? filter.value : ''}
    onChange={event => onChange(event.target.value)}
  />
)}

Most helpful comment

@tannerlinsley was correct. Moving the custom component from the render phase solved my issues.

const CustomTableFilter = ({filter, onChange}) => {
  return (
    <Input type="search" value={filter ? filter.value : ''}
      onChange={event => (event ? onChange(event.currentTarget.value) : "")}/>
  );
};

render() {
  return (
     <ReactTable
        columns={[
          {
            Filter: CustomTableFilter
          }
        ]}
     />
  );
}

All 13 comments

Would you like to open a PR to fix this regression?

I would definitely like to take a stab at it. Let me see what I can do.

Alright, I have poked around with this, and I'm still kind of confused about what's happening. It does appear to be related to my implementation, and not React Table, but I'm not sure what's changed.

Some time recently the search inputs have started losing focus, but only in development. I'm looking at the exact same code in production, and it's working fine.

It looks like I've got something like this happening:
https://github.com/tannerlinsley/react-table/issues/928

I think because I redefined the FilterComponent inside the render, and I need to define it outside the render. Let me give 6.9.0 another go, and write some better tests for my implementation....

Yeah, defining new components in any render phase will produce a lot of bugs, since React matches up component instances using references the original component you rendered. Try to hoist the component out to the instance-level, or even better, the file-level as a const.

Got it, thanks! :thumbsup:

I ran into the same issue. I did define the component outside the render phase, but without luck. Reverting to 6.8.6 did seem to fix it.

I'll try and investigate further...

@reggino I defined the component In a separate file, then imported it, and that worked for me. I can't explain why it worked before, or what changed. It seems like it shouldn't have worked...

Why is this closed? I am getting the same issue with inputs, doesn't matter if I define the input "on the fly" or as it's own component. This started in 6.9.2 for me as well, reverting back to 6.8.6 works.

Same issue here on 6.9

We might need to revert back to a previous version. We encountered a few PR's that got merged with conflicting code and are having a hard time sorting out the regression.

@tannerlinsley was correct. Moving the custom component from the render phase solved my issues.

const CustomTableFilter = ({filter, onChange}) => {
  return (
    <Input type="search" value={filter ? filter.value : ''}
      onChange={event => (event ? onChange(event.currentTarget.value) : "")}/>
  );
};

render() {
  return (
     <ReactTable
        columns={[
          {
            Filter: CustomTableFilter
          }
        ]}
     />
  );
}

Moving the columns declaration out of the render method (and using an uncontrolled input) worked for me. (Just refactoring to an external function as @boonep suggested didn't in my case.)

class AcmeCmp extends Component {
  columns = [
    {
      Header: 'header', accessor: 'acc', 
      Cell: row => (
        <input defaultValue={row.original.colId.value} 
          onChange={event => {
            const newValue = event.target.value;
            if (this.isTableValid(row.column.id, row.index, newValue)) {
              this.setState(({ data }) => ({data: [slice & insert newValue]}));
            } else {  // roll back value, as this is uncontrolled
              event.target.value = this.state.data[index][column].value;
            }
          }} />)
      },
      // other columns...
  ];
  isTableValid = (column, index, proposedValue) => { return true or false };
  render() {
    return (
        <ReactTable
          data={this.state.data}
          columns={this.columns} />
    )
  }
}

Mine wasn't working because columns was declared within the render() function, so as @tannerlinsley pointed out (if my understanding is right) the original DOM elements were no longer accessible for React to diff with, so it re-rendered everything on every edit.

@boonep

Thank you so much! Its work for me.
I think its caused because Filter returned an anon function and jsx inside that function just replace old jsx, not update.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ocalde picture ocalde  路  3Comments

monarajhans picture monarajhans  路  3Comments

dilipsundarraj1 picture dilipsundarraj1  路  3Comments

mellis481 picture mellis481  路  3Comments

danielmariz picture danielmariz  路  3Comments