简体   繁体   中英

How to use useref() to target dynamic material-ui tabs?

I am in position where I need to upload files to a particular channel but whats happening is , it's always uploaded to 1st tab/channel.

I am trying to use useRef to achieve it but don't know exactly what is missing ?

By tab I mean material-ui tabs

Consider values of tab as 0 ,1 and 2 respectively.

I'v tried to replicate the same in codesandbox here

Issue

try to add any image by clicking attach icon in tab 2 or 3 , it will be shown in tab 1.

  const fileRef = useRef(tab); // tab value can be 0,1 or 2

  useEffect(() => {
    setProgress(0);
  }, [file]);

  const [handleSubmit, loading] = usePromise(() =>
    onSend(text, fileKey).then(
      () => {
        setText('');
        setFile();
        setProgress(0);
        setFileKey();
      },
      (e) => snack.error(e.message),
    ),
  );

  const onFileSelect = (e) => {
    const { files } = e.target;
    const f = files[0];
    setFile(f);
    fileRef.current.value = '';

    const key = uuidv4() + '_' + f.name;
    setUploading(true);
    Storage.put(key, f, {
      progressCallback: (progress) => {
        const pc = (progress.loaded / progress.total) * 100;
        setProgress(`Uploading... ${Math.round(pc)}%`);
      },
    })
      .then((result) => {
        setFileKey(result.key);
        setUploading(false);
      })
      .catch((err) => {
        setUploading(false);
        snack.error(err.message);
      });
  };


  return (
    <div className={classes.root}>
      {file && (
        <FilePreview
          loading={uploading}
          progress={progress}
          file={file}
          onDelete={onDeleteFile}
        />
      )}
      <div className={classes.inputContainer}>
        <div className={classes.actions}>
          <div className={classes.upload}>
            <IconButton component="label" htmlFor="file-input">
              <AttachFileIcon />
            </IconButton>
            <input
              accept={FILE_TYPES}
              ref={fileRef}
              id="file-input"
              type="file"
              onChange={onFileSelect}
            />
          </div>
          <IconButton
            color="primary"
            disabled={loading || uploading || !(text || fileKey)}
            onClick={handleSubmit}
          >
            <SendIcon />
          </IconButton>
        </div>
      </div>
    </div>

The issue with your code is on this particular area:

<IconButton component="label" htmlFor="file-input">
  <AttachFileIcon />
</IconButton>
<input
  accept={FILE_TYPES}
  ref={fileRef}
  id="file-input"
  type="file"
  onChange={onFileSelect}
/>

Definition of for (or htmlFor in React)

The id of a labelable form-related element in the same document as the element. The first element in the document with an id matching the value of the for attribute is the labeled control for this label element, if it is a labelable element. If it is not labelable then the for attribute has no effect. If there are other elements which also match the id value, later in the document, they are not considered.

So in short, since all of the label are pointing to the same id , it will be correlated with the first instance of that input field which is the 1 on the first tab.

To fix this, simply pass different htmlFor & id for each tab specific components

<IconButton component="label" htmlFor={tab}> <-- where tab should be unique to this tab
  <AttachFileIcon />
</IconButton>
<input
  accept={FILE_TYPES}
  ref={fileRef}
  id={tab} <-- where tab should be unique to this tab
  type="file"
  onChange={onFileSelect}
/>

编辑自信鸟 nptc2

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM