简体   繁体   中英

How to focus on an input field in ReactJS when there are multiple inputs in the component?

I am working on a ReactJS application. I have a component that generates an HTML table. Using Map a child component is used to generate rows for the table. Each row contains a certain number of input fields.

When editing an input field, in certain circumstances a modal window is triggered in a parent component. The modal gives the user a choice of three buttons to click on. When a particular button in the modal is clicked, I want the focus to return to the input field the user was editing.

Can anyone give me some pointers on how to achieve this please?

I looked into using refs but all the examples I saw demonstrated it with a component that had one input. Because the modal is triggered from a parent component, I'm struggling to understand how I can use/get the ref from child component.

Appreciate any help.

I want the focus to return to the input field the user was editing.

You have multiple input fields, and you want to focus on a certain input. To be able to do that you need multiple refs --12 refs in your case--.

  1. Define your ref like this:

     const inputRef = useRef([]);
  2. You need to assign input nodes to the ref array. If you are using some kind of loop to generate the input fields, you can do it like this:

     <input ref={el => inputRef.current[i] = el} />
  3. Now, you need a variable to store the index of the input which is currently being edited.

  4. Finally, you can use this variable, which holds the index of last edited input field, to achieve what you want like this:

     inputRef.current[i].focus()

If you are using class components:

  1. In your constructor define an array:

     this.myRefs = []
  2. Assign HTML nodes like this:

     <input ref={el => this.myRefs[i] = el} />
  3. This step does not change.

  4. Now you can focus a particular input element like this:

     this.myRefs[i].focus()

Using @user9408899's answer as a guide and reading up, I came up with the following solution (only showing parts of the code directly relevant to the solution).

Parent component

  • Implemented an inputRefToFocus property to store the ref which we want to add focus to.
  • Implemented setInputRefToFocus(ref) to assign the property above in the state, also passed this and inputRefToFocus to the child component.
    export class Parent extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          ...
          // this is the ref for the input field to focus on
          // when modal window appears, depending on button clicked,
          // we want to focus on the field user was editing
          inputRefToFocus: null
        };

        this.setInputRefToFocus = this.setInputRefToFocus.bind(this);
      }

      setInputRefToFocus(ref) {
        this.setState({ inputRefToFocus: ref });
      }

      render() {
        { rows.map(elem => (
          <PivotTableRow
            setInputRefToFocus={this.setInputRefToFocus}
            inputRefToFocus={this.state.inputRefToFocus}
          />
        )) }
      }
    }

Child Component

  • When the input elements are created, each one is added to the array of refs.

  • When the input is focused, we set its ref in the parent component's inputRefToFocus property.

  • Set the focus in componentDidUpdate()
export class Child extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      ...
    };

    this.inputRef = [];

  }

  componentDidUpdate(prevProps) {
    if (this.props !== prevProps) {
      if (this.inputRef[this.props.inputRefToFocus] !== undefined) {
        this.inputRef[this.props.inputRefToFocus].focus();
      }
    }
  }

  render() {
    return (
      // loop to generate input elements
      <Input
        ref={el => { this.inputRef[dummyvalue] = el; }
        onChange={...}
        onFocus={() => this.props.setInputRefToFocus(dummyvalue)}
      /> 
    );
  }
}

I feel like the code could be improved significantly as it was my first stab at it

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM