Search code examples
reactjsrefautofocus

"Focus" prop is not changing properly between text fields in a array


I need to move the cursor downwards in the array of text fields when the "Enter" button is pressed. States change properly when I press "Enter", but the cursor doesn't move.

here is my code

import TextField from "@mui/material/TextField";

export default class BasicTextFields extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      cursor_index: 0,
      arr: ["sampledata", "sampledata", "sampledata"]
    };
    this.one = this.one.bind(this);
  }

  componentDidMount() {
   
  }

  one(e, index) {
    if (e.key === "Enter") {
      this.setState({
        cursor_index: index + 1
      });
    }
  }

  render() {
    return (
      <div>
        {this.state.arr.map((item, index) => {
          return (
            <TextField
              autoFocus={index == this.state.cursor_index}
              onKeyDown={(e) => {
                this.one(e, index);
              }}
              id="filled-basic"
              label="Filled"
              variant="filled"
            />
          );
        })}
      </div>
    );
  }
}

Solution

  • You can keep a refs array in parallel to your data array and use that information to focus on next text input.

    Pressing enter at the last input filed will get back to the first input again. You can change these edge conditions as you need.

    Try below

    import TextField from "@mui/material/TextField";
    import React, { createRef } from "react";
    
    export default class App extends React.Component {
      constructor(props) {
        super(props);
    
        this.state = {
          cursor_index: 0,
          arr: ["sampledata", "sampledata", "sampledata"],
          refs: [createRef(), createRef(), createRef()]
        };
        this.one = this.one.bind(this);
      }
    
      componentDidMount() {}
    
      one(e, index) {
        if (e.key === "Enter") {
          const { arr, refs } = this.state;
          console.log();
          refs[(index + 1) % arr.length].current.focus();
        }
      }
    
      render() {
        return (
          <div>
            {this.state.arr.map((item, index) => {
              return (
                <TextField
                  onKeyDown={(e) => {
                    this.one(e, index);
                  }}
                  inputRef={this.state.refs[index]}
                  id="filled-basic"
                  label="Filled"
                  variant="filled"
                />
              );
            })}
          </div>
        );
      }
    }
    

    code sandbox => https://codesandbox.io/s/small-waterfall-uh7p4?file=/src/App.js