如何让React组件的OnLoad事件生效?实现组件加载后单次调用函数
解决React组件加载后仅调用一次函数的问题
问题原因分析
- 直接在组件函数内调用
handleClick()会触发无限循环:组件渲染时执行该函数,函数内的setDisabled、setHighlightSection会触发组件重新渲染,重新渲染又会再次调用handleClick,陷入循环。 <div>的onLoad事件无效:该事件仅适用于<img>、<script>等需要加载外部资源的元素,普通<div>不会触发此事件。
解决方案:使用useEffect钩子
React的useEffect钩子可用于在组件挂载、更新或卸载阶段执行副作用操作。通过设置空依赖数组,能让回调函数仅在组件首次挂载(加载完成)时执行一次。
修改后的代码示例
function BadgeSample(props) { const { type, defaultValue, className, style, value, bootstrapStyle, clickable, onClickAction, getRef } = props; const [disabled, setDisabled] = React.useState(false); const [pasuedd, setPasued] = React.useState(false); const [highlightSection, setHighlightSection] = React.useState({ from: 0, to: 0 }); const synth = window.speechSynthesis; let utterance; const handleClick = () => { if (!synth) { console.error("no tts"); return; } utterance = new SpeechSynthesisUtterance(value || defaultValue); utterance.addEventListener("start", () => setDisabled(true)); utterance.addEventListener("end", () => setDisabled(false)); utterance.addEventListener("boundary", ({ charIndex, charLength }) => { setHighlightSection({ from: charIndex, to: charIndex + charLength }); }); synth.speak(utterance); }; const stoped = () => { synth.cancel(utterance); }; const pasued = () => { setPasued(true); synth.pause(utterance); }; const resumed = () => { setPasued(false); synth.resume(utterance); }; // 组件挂载后仅执行一次handleClick React.useEffect(() => { handleClick(); }, []); // 空数组表示仅在组件挂载阶段执行 return React.createElement("div", { className: "App", onClick: onClickAction, ref: getRef, style: style }, React.createElement(HighlightedText, _extends$sj({ text: value || defaultValue }, highlightSection)), React.createElement("button", { className: disabled ? "stopbtn" : "playbtn", onClick: disabled ? stoped : handleClick }, disabled ? React.createElement("div", null, React.createElement(StopCircleFill, null), "Stop") : React.createElement("div", null, React.createElement(PlayCircleFill, null), "Listen")), disabled ? React.createElement("button", { className: pasuedd ? "playbtn" : "pausebtn", onClick: pasuedd ? resumed : pasued }, pasuedd ? React.createElement("div", null, React.createElement(PlayCircleFill, null), "Resume") : React.createElement("div", null, React.createElement(PauseCircleFill, null), "Pause")) : ""); }
补充说明
如果handleClick依赖于组件的props或state(比如value、defaultValue),需要把这些依赖项加入到useEffect的依赖数组中,确保依赖变化时能正确执行。若想避免handleClick每次渲染都重新创建,可使用useCallback包裹:
const handleClick = React.useCallback(() => { // 原handleClick代码逻辑 }, [value, defaultValue, synth]); React.useEffect(() => { handleClick(); }, [handleClick]);
内容的提问来源于stack exchange,提问作者Vadim Pshenkin
相关产品推荐
相关产品推荐

