我有一个SideNav组件,其中包含动态创建的链接,这些链接需要滚动到相邻html表(InfoTable)中的相应标题。我尝试了多种不同的方法来完成此操作,但没有成功。
export default class Parent extends Component {
state = {
categories: [],
}
scrollToHeader = (tableRefString) => {
// Function to pass to SideNav to access refs in InfoTable
this[tableRefString].scrollIntoView({ block: 'start' });
}
render() {
return (
<div>
<SideNav
categories={this.state.categories}
scrollToHeader={this.scrollToHeader} />
<InfoTable
categories={this.state.categories} />
</div>
);
}
}
export default class InfoTable extends Component {
render() {
return (
<div>
<table>
<tbody>
{this.props.categories.map(category => (
<>
// Forward the ref through InfoTableHeader to be set on the parent DOM node of each InfoTableHeader
<InfoTableHeader />
{category.inputs.map(input => <InfoTableRow />)}
</>
))}
</tbody>
</table>
</div>
);
}
}
Run Code Online (Sandbox Code Playgroud)
为了单击SideNav上的链接并滚动到InfoTable上的相应标题,我相信我需要转发基于我的类别数组中的名称在Parent上动态创建的引用,并将这些引用设置为DOM中每个标题的DOM节点。信息表。从那里,我会将一个函数传递给SideNav,该函数可以访问Parent中的引用以滚动到标题。
Sam*_*rad 42
我知道有一个已经被接受的答案,虽然我发现@nicholas-haley 的解决方案是可以接受的。我认为更好的方法是使用内置useImperativeHandle钩子。
重要提示:React Hooks Api 可用
- react@16.8.0 及更高版本
- react-native@0.59.0 及更高版本
useImperativeHandle自定义使用 ref 时暴露给父组件的实例值。与往常一样,在大多数情况下应该避免使用 refs 的命令式代码。useImperativeHandle 应该与 `forwardRef 一起使用
此注释后跟以下示例:
function FancyInput(props, ref) {
const inputRef = useRef();
useImperativeHandle(ref, () => ({
focus: () => {
inputRef.current.focus();
}
}));
return <input ref={inputRef} ... />;
}
FancyInput = forwardRef(FancyInput);
Run Code Online (Sandbox Code Playgroud)
因此,在我看来,一个更简洁的解决方案是通过useImperativeHandle钩子委托所需的引用。
这样就不需要特殊的 ref 语法,组件可以简单地返回一个特定类型的 FatherRef;例子:
// LabelInput.js
function LabelInput(props, ref) {
const labelRef = useRef();
const inputRef = useRef();
useImperativeHandle(ref, () => ({
focus: () => {
inputRef.current.focus();
},
get input() {
return inputRef.current;
},
get label() {
return labelRef.current;
},
// ... whatever else one may need
}));
return (
<div>
<label ref={labelRef} ... />
<input ref={inputRef} ... />;
</div>
)
}
LabelInput = forwardRef(LabelInput);
function MyScreen() {
const labelInputRef = useRef();
const onClick = useCallback(
() => {
// labelInputRef.current.focus(); // works
// labelInputRef.current.input.focus(); // works
// ... etc
},
[]
);
return (
...
<LabelInput ref={labelInputRef} ... />
....
)
}
Run Code Online (Sandbox Code Playgroud)
我遇到过类似的情况,我需要将多个引用转发给我的Parent组件的孩子。
我仍然没有找到一个优雅的解决方案,但是您可以尝试将ref作为对象传递,并在forwardRef回调中进行分解:
// Parent
ref={{
ref1: this.ref1,
ref2: this.ref2
}}
Run Code Online (Sandbox Code Playgroud)
// Child
export default React.forwardRef((props, ref) => {
const { ref1, ref2 } = ref;
return (
<Child1
{...props}
ref={ref1}
/>
<Child2
{...props}
ref={ref2}
/>
);
});
Run Code Online (Sandbox Code Playgroud)
我不是此处命名的忠实拥护者(我更喜欢ref称呼refs),但这可以在您遇到紧急情况时起作用。
| 归档时间: |
|
| 查看次数: |
2926 次 |
| 最近记录: |