在反应中处理循环内的ref

时间:2018-09-21 16:55:45

标签: javascript reactjs

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

class TestRef extends React.Component {
  ref = React.createRef();
  state = {
    data: [
      {
        name: "abc"
      },
      { name: "def" }
    ]
  };
  focusInput = () => this.ref.current.focus();
  render() {
    return (
      <div>
        {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>
      </div>
    );
  }
}

4 个答案:

答案 0 :(得分:6)

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

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 (
      <div>
        {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>
      </div>
    );
  }
}

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

<div id="root"></div>

答案 1 :(得分:5)

如果您要提出2020年的问题,这里是如何使用循环中的创建钩子创建多个引用

   const MyComponent=(){
    // empty list to put our refs in
    let LiRefs = []

    return (
        <React.Fragment>
          <ul className="event-list">
// this part i am checking if my data exist first other wise load spinner 
            {newData ? (
              newData.map((D) => {
// the cool part inside the loop 
//create new ref 
//push it into arr 

                const newRef = createRef();
                LiRefs.push(newRef);
                return (
// link it to ur li 
// voila you have list of refs that points to your list items 
                  <li key={D._id} ref={newRef}>
                    title : {D.title} <br />
                    description : {D.description}
                    <br />
                    data : {D.date} <br />
                    price : {D.price}
                    <br />
                    <div>creator : {D.creator.username}</div>
                    {authData.token && (
                      <button type="button" id={D._id} onClick={handelBooking}>
                        Book
                      </button>
                    )}
                  </li>
                );
              })
            ) : (
              <Spinner />
            )}
          </ul>
        </React.Fragment>
      );
 }

答案 2 :(得分:0)

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

let dataCount = 0;

class TestRef extends React.Component {
  state = {
    data: [
      {
        name: "abc"
      },
      { name: "def" }
    ]
  };
  focusInput = (thisHello) => this[`ref${thisHello}`].current.focus();
  render() {
    return (
      <div>
        {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>
      </div>
    );
  }
}

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

答案 3 :(得分:0)

使用常规用途焦点挂钩

cols = [[c, c+"_new"] for c in df.columns[::2]]

您可以在此处找到更多信息:Set focus on input after render