I've made a list of refs for each of my components that is being rendered in a map, I am assigning a ref to a button within EditWebAppTypeForm
and am trying to use it within MappedAccordion
but it shows undefined? what can I do to make sure ref is set before passing it in the MappedAccordion
component?
The information logged in addtoRefs
function is correct, it shows -
(2) [button, button]
I've removed a lot of the code so its easier to read.
function Admin() {
const allRefs = useRef([] as any);
allRefs.current = [];
const addtoRefs = (e: any) => {
if (e && !allRefs?.current?.includes(e)) {
allRefs?.current?.push(e);
}
console.log(allRefs.current); <-- Logs correct info
};
return (
<div className="adminContainer">
<Grid container spacing={2}>
<Grid item md={8} xs={12} sm={12}>
<div style={{ width: 725, paddingBottom: 150 }}>
{webAppTypes &&
webAppTypes.map((a: IWebAppType, index: number) => {
return (
<>
<Accordion
key={a.id}
defaultExpanded={a.id === 0 ? true : false}
>
<AccordionDetails>
<EditWebAppTypeForm
key={a.name}
setWebAppTypes={setWebAppTypes}
IWebAppTypeModel={a}
ref={addtoRefs} // <-- returning ref to add to list
/>
<MappedAccordion
waobj={a}
key={a.id}
setWebAppTypes={setWebAppTypes}
editRef={allRefs.current[index]} <-- using ref but showing undefined in MappedAccordion component
/>
</AccordionDetails>
</Accordion>
</>
);
})}
</div>
</Grid>
</Grid>
</div>
);
}
export default Admin;
EditWebAppTypeForm Component -
const EditWebAppTypeForm = (props: any, ref: any) => {
return (
<div className="editWebAppSContainer">
<form onSubmit={handleSubmit(onSubmit)} id="edit-app-form">
<button hidden={true} ref={ref} type="submit" /> // <-- Assiging ref to button
</form>
</div>
);
};
export default forwardRef(EditWebAppTypeForm);
type MappedAccordionProps = {
waobj: IWebAppType;
setWebAppTypes: Dispatch<SetStateAction<IWebAppType[]>>;
editRef: any;
};
function MappedAccordion({
waobj,
setWebAppTypes,
editRef,
}: MappedAccordionProps) {
const onSubmit = (data: FormFields) => {
console.log(editRef); // <-- Logs undefined
};
return (
<div>
<form onSubmit={handleSubmit(onSubmit)} id="environment-form">
</form>
</div>
);
}
export default MappedAccordion;
CodePudding user response:
I would create an extra component WebAppTypeAccordion
like this :
function WebAppTypeAccordion({a, setWebAppTypes}) {
const [formEl, setFormEl] = useState(null);
function handleRef(el) {
if (el) {
setFormEl(el)
}
}
return (
<Accordion defaultExpanded={a.id === 0}>
<AccordionDetails>
<EditWebAppTypeForm
setWebAppTypes={setWebAppTypes}
IWebAppTypeModel={a}
ref={handleRef}
/>
<MappedAccordion
waobj={a}
setWebAppTypes={setWebAppTypes}
editRef={formEl}
/>
</AccordionDetails>
</Accordion>
);
}
Then you can update the Admin
component :
webAppTypes.map((a: IWebAppType) => (
<WebAppTypeAccordion key={a.id] a={a} setWebAppTypes={setWebAppTypes} />
))