Home > Back-end >  list of ref shows undefined when logging
list of ref shows undefined when logging

Time:05-27

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} />
))
  • Related