10

更新:我的问题实际上是由于拼写错误 - 如果您想在子组件和父组件中使用子元素 ref,一般方法可以正常工作。

这是有效方法的一个工作示例: https ://codesandbox.io/s/rwj7z7o7oo


原帖:

我正在尝试将 ref 转发给父组件,同时还使子组件(这是一个类)中的函数可以访问 ref。目前,我可以成功地将 ref 传递给父级,但在子级中不再可以访问 ref。

class Child extends React.Component {
    // Unable to access the forwarded ref here:
    componentDidMount() {
        console.log(this.props.forwardedRef); // null
    }

    render() {
        return <input type="text" ref={this.props.forwardedRef} />
    }
}

// Parent is able to access the ref:
const Parent = () => {
    const childRef = useRef(null);

    function handleClick() {
        console.log(childRef.current); // correctly ref's the input el
    }

    return (
        <Child forwardedRef={childRef} onClick={handleClick} />
    );
}

是否有另一种方法可以让我在 Child 和 Parent 中使用 ref?

4

2 回答 2

13

useRef返回类似于实例变量类的值。在您的情况下,即使您设置了 ref 并因此子组件的 componentDidUpdate 不会运行,也没有什么会导致组件呈现。

此外,您还没有从 Child 组件返回任何内容。

class Child extends React.Component {
  // Unable to access the forwarded ref here:
  componentDidUpdate(prevProps) {
    console.log(this.props.forwardedRef); // null
    console.log(prevProps.forwardedRef); // null
  }

  render() {
    return (
      <React.Fragment>
        <input type="text" ref={this.props.forwardedRef} />
        <div>{this.props.count}</div>
        <input type="button" onClick={this.props.onClick} value={"Click"} />
      </React.Fragment>
    );
  }
}

// Parent is able to access the ref:
const Parent = () => {
  const childRef = useRef(null);
  const [count, setCount] = useState(0);

  function handleClick() {
    console.log(childRef.current); // correctly ref's the input el
    setCount(count => count + 1);
  }

  return <Child forwardedRef={childRef} count={count} onClick={handleClick} />;
};

工作演示

于 2018-11-22T05:28:27.517 回答
3

反应钩子

无需传入forwardedRefReact 钩子。

ref您可以直接在forwardRef函数中访问变量:

const Child = React.forwardRef((_props, ref) => {
  React.useLayoutEffect(() => {
    if (ref.current) {
      ref.current.insertAdjacentHTML(
        "beforeend",
        "<span>Ref works in child</span>"
      );
    }
  }, [ref]);

  return (
    <div className="child" ref={ref}>
      <h2>Child Component</h2>
    </div>
  );
});

const Parent = () => {
  const childRef = React.useRef(null);

  React.useLayoutEffect(() => {
    if (childRef.current) {
      childRef.current.insertAdjacentHTML(
        "afterbegin",
        "<span>Ref works in parent</span>"
      );
    }
  }, []);

  return (
    <div className="parent">
      <h1>Parent Component</h1>
      <Child ref={childRef} />
    </div>
  );
};

function App() {
  return (
    <div className="App">
      <Parent />
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(
  <App />,
  rootElement
);
.App {
  font-family: sans-serif;
  text-align: center;
  padding: 1rem;
}

.parent {
  border: 1px dashed red;
  padding: 1rem;
}

.child {
  border: 1px dashed blue;
  padding: 1rem;
}

span {
  display: block;
  padding-top: 0.5rem;
  padding-bottom: 0.5rem;
  margin: 0.5rem;
  color: #777;
  border: 1px dashed #999;
}
<div id="root"></div>
<script src="https://unpkg.com/react@17/umd/react.development.js" crossorigin></script>
  <script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js" crossorigin></script>

于 2021-08-23T06:32:20.807 回答