我有一个table
列表,其中每一行都有一个menu
按钮,为此我需要一个ref
。我在我的项目中使用react mui,它是menu。我试过创建这样的裁判:
const {rows} = props;
const refs = Array.from({length: rows.length}, a => React.useRef<HTMLButtonElement>(null));
然后尝试在每个map
上使用button
函数内部:
<Button
ref={refs[index]}
aria-controls="menu-list-grow"
aria-haspopup="true"
onClick={() => handleToggle(row.id)}
>Velg
</Button>
<Popper open={!!checkIfOpen(row.id)} anchorEl={refs[index].current} keepMounted transition disablePortal>
{({TransitionProps, placement}) => (
<Grow
{...TransitionProps}
style={{transformOrigin: placement === 'bottom' ? 'center top' : 'center bottom'}}>
<Paper id="menu-list-grow">
<ClickAwayListener onClickAway={(e) => handleClose(e, refs[index].current)}>
<MenuList>
<MenuItem
onClick={(e) => handleClose(e, refs[index].current)}>Profile</MenuItem>
<MenuItem onClick={(e) => handleClose(e, refs[index].current)}>My account</MenuItem>
<MenuItem onClick={(e) => handleClose(e, refs[index].current)}>Logout</MenuItem>
</MenuList>
</ClickAwayListener>
</Paper>
</Grow>
)}
</Popper>
但是,然后我得到一个错误:
反应挂钩“ React.useRef”不能在回调内调用。反应 挂钩必须在React函数组件或自定义React中调用 挂钩函数react-hooks / rules-of-hooks
如何动态执行此操作,以便可以在map函数中使用引用。我已经尝试了答案中的建议,但无法正常工作。 这是codesandbox of the example。
答案 0 :(得分:1)
这是另一种选择:
const textInputRefs = useRef<(HTMLDivElement | null)[]>([])
...
const onClickFocus = (event: React.BaseSyntheticEvent, index: number) => {
textInputRefs.current[index]?.focus()
};
...
{items.map((item, index) => (
<textInput
inputRef={(ref) => textInputs.current[index] = ref}
/>
<Button
onClick={event => onClickFocus(event, index)}
/>
}
答案 1 :(得分:0)
useRef
与React.createRef不完全相同。
最好将其称为useInstanceField
:)
因此,您的代码可能会有所不同。
第一步:我们使用useRef
保存引用数组:
const {rows} = props;
const refs = useRef(Array.from({length: rows.length}, a => React.createRef()));
然后,在您的map函数中,我们将每个ref保存到refs数组中的索引:
<Button
ref={refs.current[index]}
aria-controls="menu-list-grow"
aria-haspopup="true"
onClick={() => handleToggle(row.id)}
>Velg
</Button>
<Popper open={!!checkIfOpen(row.id)} anchorEl={refs.current[index].current} keepMounted transition disablePortal>
{({TransitionProps, placement}) => (
<Grow
{...TransitionProps}
style={{transformOrigin: placement === 'bottom' ? 'center top' : 'center bottom'}}>
<Paper id="menu-list-grow">
<ClickAwayListener onClickAway={(e) => handleClose(e, refs.current[index].current)}>
<MenuList>
<MenuItem
onClick={(e) => handleClose(e, refs.current[index].current)}>Profile</MenuItem>
<MenuItem onClick={(e) => handleClose(e, refs.current[index].current)}>My account</MenuItem>
<MenuItem onClick={(e) => handleClose(e, refs.current[index].current)}>Logout</MenuItem>
</MenuList>
</ClickAwayListener>
</Paper>
</Grow>
)}
</Popper>
如果您更改了长度,则应在useEffect
中对其进行处理以更改裁判的长度
您还可以使用另一种方式:
1)创建一个引用数组,但没有React.createRef:
const {rows} = props;
const refs = useRef(new Array(rows.length));
在地图中,我们使用ref={el => refs.current[index] = el}
存储参考
<Button
ref={el => refs.current[index] = el}
aria-controls="menu-list-grow"
aria-haspopup="true"
onClick={() => handleToggle(row.id)}
>Velg
</Button>
<Popper open={!!checkIfOpen(row.id)} anchorEl={refs.current[index].current} keepMounted transition disablePortal>
{({TransitionProps, placement}) => (
<Grow
{...TransitionProps}
style={{transformOrigin: placement === 'bottom' ? 'center top' : 'center bottom'}}>
<Paper id="menu-list-grow">
<ClickAwayListener onClickAway={(e) => handleClose(e, refs.current[index])}>
<MenuList>
<MenuItem
onClick={(e) => handleClose(e, refs.current[index])}>Profile</MenuItem>
<MenuItem onClick={(e) => handleClose(e, refs.current[index])}>My account</MenuItem>
<MenuItem onClick={(e) => handleClose(e, refs.current[index])}>Logout</MenuItem>
</MenuList>
</ClickAwayListener>
</Paper>
</Grow>
)}
</Popper>