React中能否向子组件传递函数数组?如何正确实现?
问题根因
你的写法失效是两个错误导致的:
- JSX语法规则要求,所有非字符串类型的属性值(包括数组、函数、对象、数值)必须用
{}包裹,你直接写funcList=[xxx]不符合语法规范,会直接触发解析错误。 - 你写的
doUserRegistration()、notAccept()带了函数调用括号,会导致组件渲染时就立刻执行这两个函数,而不是把函数作为引用存入数组传给子组件,业务逻辑会直接在页面加载时触发,完全不符合预期。
基础实现方案
第一步:修正父组件传参写法
去掉函数后面的调用括号,把整个数组用大括号包裹,同时记得把之前注释掉的openBox控制属性传回去,否则弹窗无法正常显隐:
<ConfirmationBox funcList={[doUserRegistration, notAccept]} openBox={openBox} title={"Kayıt olmak istediğine emin misin ?"} context={"Kabul etmen durumunda deneme sürümü ve paketler konusunda sizinle iletişime geçeceğiz."} />
第二步:子组件接收并调用
在ConfirmationBox组件中解构拿到funcList后,按照索引调用对应函数即可,建议加可选链避免未传函数时的报错:
const ConfirmationBox = ({ funcList, openBox, title, context }) => { // 索引0为确认逻辑doUserRegistration,索引1为取消逻辑notAccept const handleConfirm = () => { funcList[0]?.(); } const handleCancel = () => { funcList[1]?.(); } return ( // 原有弹窗UI逻辑,将确认、取消按钮的点击事件绑定到上面两个处理函数即可 <div className="confirmation-modal" style={{ display: openBox ? 'block' : 'none' }}> <h3>{title}</h3> <p>{context}</p> <button onClick={handleCancel}>取消</button> <button onClick={handleConfirm}>确认</button> </div> ) }
可选优化(避免无效重渲染)
上面的基础写法已经可以正常运行,但每次父组件重渲染都会生成新的数组引用,如果你的ConfirmationBox组件用React.memo做了渲染优化,会触发不必要的子组件重渲染,可以做两处调整:
- 用
useCallback包裹两个业务函数,固定函数引用:
// notAccept函数没有依赖外部可变变量,依赖数组为空 const notAccept = useCallback(async function () { setOpenBox(false); }, []); // doUserRegistration用到了username、password、password2、history,全部加入依赖数组 const doUserRegistration = useCallback(async function () { const usernameValue = username; const passwordValue = password; const passwordValue2 = password2; if (passwordValue === passwordValue2) { try { const createdUser = await Parse.User.signUp(usernameValue, passwordValue); alert( `Success! User ${createdUser.getUsername()} was successfully created!` ); createdUser.set("level", "admin"); await createdUser.save(); setOpenBox(false); history("/addCompanyInfo"); return true; } catch (error) { setOpenBox(false); alert(`Error! ${error}`); return false; } } else{ alert('password is not matching!'); window.location.reload(); } }, [username, password, password2, history]);
- 用
useMemo包裹函数数组,固定数组引用:
const funcList = useMemo(() => [doUserRegistration, notAccept], [doUserRegistration, notAccept]);
调整后传参直接使用预定义的funcList变量即可:
<ConfirmationBox funcList={funcList} openBox={openBox} title={"Kayıt olmak istediğine emin misin ?"} context={"Kabul etmen durumunda deneme sürümü ve paketler konusunda sizinle iletişime geçeceğiz."} />
内容的提问来源于stack exchange,提问作者aborted
相关产品推荐
相关产品推荐

