使用 autoFocus 在 React 侧边菜单中的按钮之间切换焦点
Toggle focus between buttons in a side menu in React using autoFocus
我正在尝试在侧边菜单中的按钮之间切换焦点。被点击的按钮应该被聚焦。
我的侧边菜单代码:
import React, { useRef } from "react";
import styles from "./SideMenu.module.scss";
interface Props {
buttons: Array<any>;
clicked: Function;
}
const sideMenu: React.FC<Props> = ({ buttons, clicked }) => {
const buttonsList = buttons.map((b, index) => {
return (
<button
key={b.label}
id={b.label}
autoFocus={b.isSelected}
onClick={() => clicked(b.label)}>
{b.label.toUpperCase()}
</button>
);
});
return <div className={styles.sideMenu}>{buttonsList}</div>;
};
export default sideMenu;
这里是点击时改变按钮状态的代码
const layout: React.FC<{}> = ({ children }) => {
const [buttons, setButtons] = useState([
{ label: "btn1", isSelected: true, routePath: "/btn1" },
{ label: "btn2", isSelected: false, routePath: "/btn2" },
]);
const router = useRouter()
const clickButtonHandler = (buttonLabel: string) => {
const updatedButtons = [...buttons];
let path = "/";
updatedButtons.map((b, index) => {
if (b.label === buttonLabel) {
b.isSelected = true
path = b.routePath
} else {
b.isSelected = false
}
});
setButtons(updatedButtons)
router.push(path)
};
return (
<div className={styles.mainWrapper}>
<h1 className={styles.mainHeader}>My Web App</h1>
<div className={styles.wrapper}>
<SideMenu buttons={buttons} clicked={clickButtonHandler} />
<div className={styles.content}>{children}</div>
</div>
</div>
);
};
export default layout;
当我呈现页面时,btn1 自动聚焦(这是预期的),当我单击 btn2 时,焦点首先变为 btn2 但随后 立即返回到 btn1,如果我再次点击btn2,焦点会变成btn2并停留
但是每次点击btn1,焦点都会切换到btn1并停留
如果我注释掉“router.push(path)”,聚焦行为会正常工作。
如何在不注释“router.push(path)”的情况下让它工作?
autoFocus
在您的控件未放置在 <form>
标记内之前无法正常工作。您可以呈现表单,但有一种方法“更 React”。
const sideMenu: React.FC<Props> = ({ buttons, clicked }) => {
const focusedButton = null;
useEffect(() => {
if(focusedButton) focusedButton.focus();
});
const buttonsList = buttons.map((b, index) => {
return (
<button
key={b.label}
id={b.label}
ref={el => {focusedButton = b.isSelected ? el : focusedButton}}
onClick={() => clicked(b.label)}>
{b.label.toUpperCase()}
</button>
);
});
return <div className={styles.sideMenu}>{buttonsList}</div>;
};
官方文档suggests using ref
for focusing elements. Here is关于 ref 回调的更多详细信息。
我正在尝试在侧边菜单中的按钮之间切换焦点。被点击的按钮应该被聚焦。 我的侧边菜单代码:
import React, { useRef } from "react";
import styles from "./SideMenu.module.scss";
interface Props {
buttons: Array<any>;
clicked: Function;
}
const sideMenu: React.FC<Props> = ({ buttons, clicked }) => {
const buttonsList = buttons.map((b, index) => {
return (
<button
key={b.label}
id={b.label}
autoFocus={b.isSelected}
onClick={() => clicked(b.label)}>
{b.label.toUpperCase()}
</button>
);
});
return <div className={styles.sideMenu}>{buttonsList}</div>;
};
export default sideMenu;
这里是点击时改变按钮状态的代码
const layout: React.FC<{}> = ({ children }) => {
const [buttons, setButtons] = useState([
{ label: "btn1", isSelected: true, routePath: "/btn1" },
{ label: "btn2", isSelected: false, routePath: "/btn2" },
]);
const router = useRouter()
const clickButtonHandler = (buttonLabel: string) => {
const updatedButtons = [...buttons];
let path = "/";
updatedButtons.map((b, index) => {
if (b.label === buttonLabel) {
b.isSelected = true
path = b.routePath
} else {
b.isSelected = false
}
});
setButtons(updatedButtons)
router.push(path)
};
return (
<div className={styles.mainWrapper}>
<h1 className={styles.mainHeader}>My Web App</h1>
<div className={styles.wrapper}>
<SideMenu buttons={buttons} clicked={clickButtonHandler} />
<div className={styles.content}>{children}</div>
</div>
</div>
);
};
export default layout;
当我呈现页面时,btn1 自动聚焦(这是预期的),当我单击 btn2 时,焦点首先变为 btn2 但随后 立即返回到 btn1,如果我再次点击btn2,焦点会变成btn2并停留
但是每次点击btn1,焦点都会切换到btn1并停留
如果我注释掉“router.push(path)”,聚焦行为会正常工作。
如何在不注释“router.push(path)”的情况下让它工作?
autoFocus
在您的控件未放置在 <form>
标记内之前无法正常工作。您可以呈现表单,但有一种方法“更 React”。
const sideMenu: React.FC<Props> = ({ buttons, clicked }) => {
const focusedButton = null;
useEffect(() => {
if(focusedButton) focusedButton.focus();
});
const buttonsList = buttons.map((b, index) => {
return (
<button
key={b.label}
id={b.label}
ref={el => {focusedButton = b.isSelected ? el : focusedButton}}
onClick={() => clicked(b.label)}>
{b.label.toUpperCase()}
</button>
);
});
return <div className={styles.sideMenu}>{buttonsList}</div>;
};
官方文档suggests using ref
for focusing elements. Here is关于 ref 回调的更多详细信息。