Auto start webcam

HI, I’m trying to automatically start the webcam once my dashboard has been rendered. I read somewhere that uppy hasn’t introduced a feature like this, is it still the same??
I’ve also been trying to use scripts like below

useEffect(() => {
    const uppyBtns = document.getElementsByClassName(
      "uppy-u-reset uppy-c-btn uppy-DashboardTab-btn"
    ) as HTMLCollectionOf<HTMLButtonElement>;
    console.log(uppyBtns); // returns collection of 2 items
    console.log(uppyBtns.length); // returns 0
    console.log(Array.from(uppyBtns)) // returns empty array
  }, [cameraOnly]);

The goal is to check for the uppy buttons and filter out the one referencing the camera button, once filtered, call the click event. But this proved difficult because I couldn’t access the uppyBtns collection, and I still don’t know why. PS: querySelectorAll also didn’t work.
I don’t really care about the means so could anyone help me out with this?

I think you can do this instead:

uppy.getPlugin('Dashboard').showPanel('Webcam')

It returns error property showPanel doesn’t exist

Probably a race condition depending on your React code. The Dashboard first needs to be rendered, but you’re likely calling this before the return of that component.

Actually I tested this now on Uppy and indeed you can’t get React components of Uppy with getPlugin(). I’ll take a look if that can be fixed.

1 Like

Okay, please update me if you find anything

Actually it is possible, I just used the wrong ID :see_no_evil:

uppy.getPlugin('react:Dashboard').showPanel('Webcam')

It’s a bit confusing we change the ID per framework. You can also pass an id prop yourself to change this if you want.

uppy?.getPlugin("react:Dashboard")?.showPanel("Webcam");

I’m using typescript and it failed to compile saying;

Property ‘showPanel’ does not exist on type ‘UIPlugin’.

Same as before

I confirmed locally again that it does work. Check your code or share as much information as possible otherwise we can’t help you.

  useEffect(() => {
    uppy.getPlugin('dashboard').showPanel('Webcam')
  }, [])

  <Dashboard id="dashboard" uppy={uppy} plugins={['Webcam']} />

FileUploader.tsx

import { useEffect } from "react";
import { useState } from "react";
import { Uppy } from "@uppy/core";
import Webcam from "@uppy/webcam";
import ImageEditor from "@uppy/image-editor";
import { Dashboard } from "@uppy/react";

interface Props {
  cameraOnly: boolean;
}

const FileUploader = ({ cameraOnly }: Props) => {
  const [uppy, setUppy] = useState<Uppy | null>(null);

  // Create uppy instance
  useEffect(() => {
    let uppyInstance: Uppy | null = null;

    const createUppyInstance = () => {
      uppyInstance = new Uppy().use(Webcam).use(ImageEditor, {});
      setUppy(uppyInstance);
    };

    createUppyInstance();

    return () => {
      if (uppyInstance) {
        uppyInstance.close();
      }
    };
  }, []);

  // Auto open camera on isCameraOnly
  useEffect(() => {
    if (uppy) uppy?.getPlugin("dashboard")?.showPanel("Webcam");
  }, [cameraOnly]);

  return (
    <Dashboard
      uppy={uppy ? uppy : new Uppy()}
      id={"dashboard"}
      plugins={["Webcam", "ImageEditor"]}
    />
  );
};
export default FileUploader;

Returns Property 'showPanel' does not exist on type 'UIPlugin<DefaultPluginOptions> | BasePlugin<DefaultPluginOptions>'. Property 'showPanel' does not exist on type 'UIPlugin<DefaultPluginOptions>'

Is it possible my import statements are the problem or …?

You are using Uppy and React incorrectly. You have two options.

  1. Move Uppy outside of the component:
const uppy = new Uppy().use(Webcam);

function Component() {
    return <Dashboard uppy={uppy} plugins={['Webcam']} />;
}
  1. Use the initialiser function of useState:
function Component() {
    // important: passing an initialiser function to prevent the state from recreating!
    const [uppy] = useState(() => new Uppy().use(Webcam))
    return <Dashboard uppy={uppy} plugins={['Webcam']} />;
}

Lastly, do not call uppy.close(). You likely never want to call this.

1 Like

Thank you, your solution worked. I noticed that even though the app runs, typescript still refused to compile the code so I had to do this before it compiled.

useEffect(() => {
    if (uppy) {
      // Use a type assertion to inform TypeScript
      (uppy as any).getPlugin("dashboard").showPanel("Webcam");
    }
  }, [cameraOnly]);

Now it’s running without a problem.

That’s not what you want to do. This is better:

const [uppy] = useState<Uppy>(() => new Uppy().use(Webcam))

useEffect(() => {
      uppy.getPlugin<Dashboard>("dashboard").showPanel("Webcam");
  }, [cameraOnly, uppy]);
1 Like