关于javascript:在React的循环内处理ref

dealing with ref within a loop in react

以下是我的父组件,但是如何选择关注哪个输入? 在这种情况下是否必须创建动态引用?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class TestRef extends React.Component {
  ref = React.createRef();
  state = {
    data: [
      {
        name:"abc"
      },
      { name:"def" }
    ]
  };
  focusInput = () => this.ref.current.focus();
  render() {
    return (
     
        {this.state.data.map(o => {
          return <Hello placeholder={o.name} ref={this.ref} />;
        })}
        <button onClick={this.focusInput}>focus input 1</button>
        <button onClick={this.focusInput}>focus input 2</button>
     
    );
  }
}


您可以使用回调引用来生成并将每个输入的动态引用存储在数组中。 现在,您可以使用ref的索引来引用它们:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
const Hello = React.forwardRef((props,  ref) => <input ref={ref} />);

class Button extends React.Component {
  onClick = () => this.props.onClick(this.props.id);

  render() {
    return (
      <button onClick={this.onClick}>{this.props.children}</button>
    );
  }
}

class TestRef extends React.Component {
  state = {
    data: [
      {
        name:"abc"
      },
      { name:"def" }
    ]
  };
 
  inputRefs = [];
 
  setRef = (ref) => {
    this.inputRefs.push(ref);
  };
 
  focusInput = (id) => this.inputRefs[id].focus();
 
  render() {
    return (
     
        {this.state.data.map(({ name }) => (
          <Hello
            placeholder={name}
            ref={this.setRef}
            key={name} />
        ))}
        <Button onClick={this.focusInput} id={0}>focus input 1</Button>
        <Button onClick={this.focusInput} id={1}>focus input 2</Button>
     
    );
  }
}

ReactDOM.render(<TestRef />, document.getElementById("root"));
1
2
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js">
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js">


使用一般用途焦点挂钩

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// General Focus Hook
const useFocus = (initialFocus = false, id ="") => {
    const [focus, setFocus] = useState(initialFocus)
    return ([
        (newVal=true) => setFocus(newVal), {
            autoFocus: focus,
            key: `${id}${focus}`,
            onFocus: () => setFocus(true),
            onBlur: () => setFocus(false),
        },
    ])
}

const data: [{
        name:"abc"
    },{
        name:"def"
}]

const TestRef = () => {

    const focusHelper = data.map( (_,i) => {
        const [setFocus, focusProps]= useFocus(false, i)
        return {setFocus, focusProps}
    })

    return (
     
        {data.map( (o,i) => (
          <Hello placeholder={o.name} {...focusHelper[i].focusProps} />;
        ))}
        <button onClick={() => focusHelper[0].setFocus()}>focus input 1</button>
        <button onClick={() => focusHelper[1].setFocus()}>focus input 2</button>
     
    );
}

您可以在此处找到更多信息:渲染后将焦点放在输入上


我发现了另一种解决方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
let dataCount = 0;

class TestRef extends React.Component {
  state = {
    data: [
      {
        name:"abc"
      },
      { name:"def" }
    ]
  };
  focusInput = (thisHello) => this[`ref${thisHello}`].current.focus();
  render() {
    return (
     
        {this.state.data.map(o => {
          dataCount++
          return <Hello placeholder={o.name} ref={(el) => { this[`ref${dataCount}`] = el; }} />;
        })}
        <button onClick={() => this.focusInput(1)}>focus input 1</button>
        <button onClick={() => this.focusInput(2)}>focus input 2</button>
     
    );
  }
}

如果Hello元素具有用作变量的键或唯一ID,则不需要dataCount