123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228 |
- ---
- slug: /react
- ---
- import Tabs from '@theme/Tabs';
- import TabItem from '@theme/TabItem';
- # React
- [React][] components for the Uppy UI plugins and a `useUppyState` hook.
- ## Install
- <Tabs>
- <TabItem value="npm" label="NPM" default>
- ```shell
- npm install @uppy/react
- ```
- </TabItem>
- <TabItem value="yarn" label="Yarn">
- ```shell
- yarn add @uppy/react
- ```
- </TabItem>
- </Tabs>
- :::note
- You also need to install the UI plugin you want to use. For instance,
- `@uppy/dashboard`.
- :::
- ## Use
- `@uppy/react` exposes component wrappers for `Dashboard`, `DragDrop`, and all
- other UI elements. The components can be used with either [React][] or
- API-compatible alternatives such as [Preact][].
- :::caution
- If you find yourself writing many instances of `useState` and `useEffect` to
- achieve something with Uppy in React, you are most likely breaking React best
- practices. Consider reading
- “[You Might Not Need an Effect](https://react.dev/learn/you-might-not-need-an-effect)”
- and looking at our examples below.
- :::
- ### Components
- The following components are exported from `@uppy/react`:
- - `<Dashboard />` renders [`@uppy/dashboard`](/docs/dashboard)
- - `<DragDrop />` renders [`@uppy/drag-drop`](/docs/drag-drop)
- - `<ProgressBar />` renders [`@uppy/progress-bar`](/docs/progress-bar)
- - `<StatusBar />` renders [`@uppy/status-bar`](/docs/status-bar)
- {/* prettier-ignore */}
- {/* Commented out until the hook is live
- ### Hooks
- `useUppyState(uppy, selector)`
- Use this hook when you need to access Uppy’s state reactively. Most of the
- times, this is needed if you are building a custom UI for Uppy in React.
- ```js
- // IMPORTANT: passing an initializer function to prevent Uppy from being reinstantiated on every render.
- const [uppy] = useState(() => new Uppy());
- const files = useUppyState(uppy, (state) => state.files);
- const totalProgress = useUppyState(uppy, (state) => state.totalProgress);
- // We can also get specific plugin state.
- // Note that the value on `plugins` depends on the `id` of the plugin.
- const metaFields = useUppyState(
- uppy,
- (state) => state.plugins?.Dashboard?.metaFields,
- );
- ```
- You can see all the values you can access on the
- [`State`](https://github.com/transloadit/uppy/blob/main/packages/%40uppy/core/types/index.d.ts#L190)
- type. If you are accessing plugin state, you would have to look at the types of
- the plugin.
- \*/}
- ## Examples
- ### Example: basic component
- Here we have a basic component which ties Uppy’s state to the component. This
- means you can render multiple instances. But be aware that as your component
- unmounts, for instance because the user navigates to a different page, Uppy’s
- state will be lost and uploads will stop.
- :::note
- If you render multiple instances of Uppy, make sure to give each instance a
- unique `id`.
- :::
- ```js
- import React, { useEffect, useState } from 'react';
- import Uppy from '@uppy/core';
- import Webcam from '@uppy/webcam';
- import { Dashboard } from '@uppy/react';
- import '@uppy/core/dist/style.min.css';
- import '@uppy/dashboard/dist/style.min.css';
- import '@uppy/webcam/dist/style.min.css';
- function Component() {
- // IMPORTANT: passing an initializer function to prevent Uppy from being reinstantiated on every render.
- const [uppy] = useState(() => new Uppy().use(Webcam));
- return <Dashboard uppy={uppy} plugins={['Webcam']} />;
- }
- ```
- ### Example: keep Uppy state and uploads while navigating between pages
- When you want Uppy’s state to persist and keep uploads running between pages,
- you can
- [lift the state up](https://react.dev/learn/sharing-state-between-components#lifting-state-up-by-example).
- ```js
- import React, { useState, useEffect } from 'react';
- import Uppy from '@uppy/core';
- import { Dashboard } from '@uppy/react';
- function Page1() {
- // ...
- }
- function Page2({ uppy }) {
- return (
- <>
- <p>{totalProgress}</p>
- <Dashboard id="dashboard" uppy={uppy} />
- </>
- );
- }
- export default function App() {
- // keeping the uppy instance alive above the pages the user can switch during uploading
- const [uppy] = useState(() => new Uppy());
- return (
- // Add your router here
- <>
- <Page1 />
- <Page2 uppy={uppy} />
- </>
- );
- }
- ```
- ### Example: updating Uppy’s options dynamically based on props
- ```js
- // ...
- function Component(props) {
- // IMPORTANT: passing an initializer function to prevent the state from recreating.
- const [uppy] = useState(() => new Uppy().use(Webcam));
- useEffect(() => {
- uppy.setOptions({ restrictions: props.restrictions });
- }, [props.restrictions]);
- useEffect(() => {
- uppy.getPlugin('Webcam').setOptions({ modes: props.webcamModes });
- }, [props.webcamModes]);
- return <Dashboard uppy={uppy} plugins={['Webcam']} />;
- }
- ```
- ### Example: dynamic params and signature for Transloadit
- When you go to production always make sure to set the `signature`. **Not using
- [Signature Authentication](https://transloadit.com/docs/topics/signature-authentication/)
- can be a security risk**. Signature Authentication is a security measure that
- can prevent outsiders from tampering with your Assembly Instructions.
- Generating a signature should be done on the server to avoid leaking secrets. In
- React, this could get awkward with a `fetch` in a `useEffect` and setting it to
- `useState`. Instead, it’s easier to use the
- [`assemblyOptions`](/docs/transloadit#assemblyoptions) option to `fetch` the
- params.
- ```js
- // ...
- function createUppy(userId) {
- return new Uppy({ meta: { userId } }).use(Transloadit, {
- async assemblyOptions(file) {
- // You can send meta data along for use in your template.
- // https://transloadit.com/docs/topics/assembly-instructions/#form-fields-in-instructions
- const body = JSON.stringify({ userId: file.meta.userId });
- const res = await fetch('/transloadit-params', { method: 'POST', body });
- return response.json();
- },
- });
- }
- function Component({ userId }) {
- // IMPORTANT: passing an initializer function to prevent Uppy from being reinstantiated on every render.
- const [uppy] = useState(() => createUppy(userId));
- useEffect(() => {
- if (userId) {
- // Adding to global `meta` will add it to every file.
- uppy.setOptions({ meta: { userId } });
- }
- }, [uppy, userId]);
- }
- ```
- [react]: https://facebook.github.io/react
- [preact]: https://preactjs.com/
|