如果我不拥有该代码,如何将 Ref 分配给 React 组件中的按钮?我想集中注意力
Posted
技术标签:
【中文标题】如果我不拥有该代码,如何将 Ref 分配给 React 组件中的按钮?我想集中注意力【英文标题】:How to assign a Ref to a button in a React component if I don't own that code? I want to focus it 【发布时间】:2022-01-04 09:47:12 【问题描述】:我正在研究 React。还有一个团队向我们展示了一个组件,其中有一个按钮。它是我们存储库的依赖项。我希望在完成特定操作时使该按钮成为焦点。我想使用 refs 或任何其他可接受的方式来做到这一点。
myCode.js
focusExternalButton()
// some code that focuses the button in the external component
render()
return
<div>
<ExternalButtonComponent/>
<button onClick=this.focusExternalButton>submit</button>
</div>
ExternalButtonComponent.js
render()
return <div><button id="btn-external">This is a button</button></div>
当我点击我的按钮时,如何将焦点放在外部按钮上?我正在考虑参考,但我不确定如何实现它。
【问题讨论】:
按钮部分属于哪个库?你读过文档吗?很可能已经有一个内置的解决方案。 该库归我组织中的另一个团队所有。我可以要求他们为此公开一个参考。但在我联系他们之前,我只想确保没有其他方法。 @pilchard 您不能使用 ref,因为如果按钮组件未配置为接收它,它将被按钮组件忽略。此外,不能保证返回的 html 的内部结构会保持一致。实现它的一个 hacky 方法是查询useLayoutEffect
中的按钮,但如果您可以选择让 ref 公开,那将是 much 更可取的。
@pilchard 你对使用 document.getElementById('target-id').focus() 有什么想法?这样可以集中注意力吗?
【参考方案1】:
外部组件使用id
s 让我有点吃惊,因为在一个页面中多次渲染它会导致页面上出现重复的id
s,这不是有效的 HTML。
不过,是的,您可以直接查询 DOM,不过我可能会在挂载时执行此操作,并将返回的结果元素存储在 ref
中。
const useEffect, useRef = React;
function App()
const buttonRef = useRef();
useEffect(() =>
buttonRef.current = document.getElementById('btn-external');
, []);
function focusExternalButton()
buttonRef.current.focus();
;
return (
<div>
<ExternalButtonComponent label="This is a button" />
<button type='button' onClick=focusExternalButton>submit</button>
</div>
);
function ExternalButtonComponent(label)
return <div><button id="btn-external">label</button></div>;
ReactDOM.render(
<App />,
document.getElementById("root")
);
#btn-external:focus box-shadow: 0 0 0 3px rgba(21, 156, 228, 0.4);
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
<div id="root"></div>
但是,为了避免每次使用组件时都必须这样做,您可以将外部组件和forward the ref 包装起来。
const WrappedExternalButtonComponent = forwardRef((props, ref) =>
useEffect(() =>
ref.current = document.getElementById('btn-external');
, []);
return <ExternalButtonComponent ...props />
);
const useEffect, useRef, forwardRef = React;
const WrappedExternalButtonComponent = forwardRef((props, ref) =>
useEffect(() =>
ref.current = document.getElementById('btn-external');
, []);
return <ExternalButtonComponent ...props />
);
function ExternalButtonComponent(label)
return <div><button id="btn-external">label</button></div>;
function App()
const buttonRef = useRef();
function focusExternalButton()
buttonRef.current.focus();
;
return (
<div>
<WrappedExternalButtonComponent ref=buttonRef label="This is a button" />
<button type='button' onClick=focusExternalButton>submit</button>
</div>
);
ReactDOM.render(
<App />,
document.getElementById('root')
);
#btn-external:focus box-shadow: 0 0 0 3px rgba(21, 156, 228, 0.4);
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
<div id="root"></div>
甚至可以通过创建一个实用程序来进一步概括它,该实用程序将Component
和一个查询函数作为参数并返回一个包装的组件。
const wrapExternalComponent = (Component, query) => forwardRef(( children, ...props , ref) =>
useEffect(() =>
ref.current = query();
, []);
return (
<Component ...props>
children
</Component>
);
);
const WrappedExternalButtonComponent =
wrapExternalComponent(ExternalButtonComponent, () => document.getElementById('btn-external'));
const useEffect, useRef, forwardRef = React;
const wrapExternalComponent = (Component, query) => forwardRef(( children, ...props , ref) =>
useEffect(() =>
ref.current = query();
, []);
return (
<Component ...props>
children
</Component>
);
);
function ExternalButtonComponent(label)
return <div><button id="btn-external">label</button></div>;
const WrappedExternalButtonComponent =
wrapExternalComponent(ExternalButtonComponent, () => document.getElementById('btn-external'));
function App()
const buttonRef = useRef();
function focusExternalButton()
buttonRef.current.focus();
;
return (
<div>
<WrappedExternalButtonComponent ref=buttonRef label="This is a button" />
<button type='button' onClick=focusExternalButton>submit</button>
</div>
);
ReactDOM.render(
<App />,
document.getElementById('root')
);
#btn-external:focus box-shadow: 0 0 0 3px rgba(21, 156, 228, 0.4);
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
<div id="root"></div>
【讨论】:
感谢您的回答!非常有帮助。关于您对 id 感到惊讶 - 它实际上是基于道具动态生成的,但我在尝试简化时错过了提及。 啊,我觉得这更有意义,很乐意提供帮助。以上是关于如果我不拥有该代码,如何将 Ref 分配给 React 组件中的按钮?我想集中注意力的主要内容,如果未能解决你的问题,请参考以下文章