如何处理循环中的引用?

新手上路,请多包涵

下面是我的父组件,其中包含来自循环的多个输入。我怎样才能选择一个 input 来聚焦?在这种情况下,我是否必须创建动态 ref

 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>
    );
  }
}

原文由 Alisa T Morgan 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 255
2 个回答

您可以使用 回调引用 来生成每个输入的动态引用并将其存储在数组中。现在您可以使用 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>

如果列表不是静态的,并且项目可能会被删除/替换,您可能应该使用 WeakMap 来保存引用,或者通过常量添加引用的任何其他方法 id 。您还应该在使用 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" }, { name: "ghi" }]
  };

  componentDidMount() {
    setTimeout(() => {
      this.setState(({ data }) => ({
        data: data.slice(0, -1)
      }))
    }, 3000);
  }

  inputRefs = new WeakMap;

  setRef = (id) => (ref) => {
    this.inputRefs.set(id, ref);
  };

  focusInput = (id) => {
    const input = this.inputRefs.get(id);

    if(input) input.focus(); // use only if the ref exists - use optional chaining ?. if possible instead
  }

  render() {
    const { data } = this.state;

    return (
      <div>
        {data.map(o => (
          <Hello
            placeholder={o.name}
            ref={this.setRef(o)}
            key={o.name} />
        ))}

        <br />

        {data.map((o, i) => (
          <Button onClick={this.focusInput} id={o} key={o.name}>focus input {i + 1}</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>

原文由 Ori Drori 发布,翻译遵循 CC BY-SA 4.0 许可协议

如果您要回答这个问题 2020,这里是您如何使用循环中的创建挂钩创建多个引用

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

    return (
        <React.Fragment>
          <ul className="event-list">
            // Check if my data exists first otherwise load spinner
            {newData ? (
              newData.map((D) => {
                // the cool part inside the loop
                // create new ref
                // push it into array

                const newRef = createRef();
                LiRefs.push(newRef);
                return (
                  // link it to your li
                  // now 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>
      );
 }

原文由 Ahmed Magdy 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题