From 66ce650fec2736fac30df88e93cc80030ae8312d Mon Sep 17 00:00:00 2001 From: Murderlon Date: Wed, 16 Nov 2022 14:23:27 -0300 Subject: [PATCH 1/6] Deprecate useUppy --- packages/@uppy/react/src/useUppy.d.ts | 3 + packages/@uppy/react/src/useUppy.js | 3 + website/src/docs/react-initializing.md | 63 ------------------- website/src/docs/react.md | 87 +++++++++++++------------- 4 files changed, 51 insertions(+), 105 deletions(-) delete mode 100644 website/src/docs/react-initializing.md diff --git a/packages/@uppy/react/src/useUppy.d.ts b/packages/@uppy/react/src/useUppy.d.ts index fa7f87b78d..f106a560a9 100644 --- a/packages/@uppy/react/src/useUppy.d.ts +++ b/packages/@uppy/react/src/useUppy.d.ts @@ -1,5 +1,8 @@ import type Uppy from '@uppy/core' +/** + * @deprecated Initialize Uppy outside of the component or with `useState` and `useEffect` (see docs) + */ declare function useUppy(factory: () => Uppy): Uppy export default useUppy diff --git a/packages/@uppy/react/src/useUppy.js b/packages/@uppy/react/src/useUppy.js index 399adfc4ce..0822995bdf 100644 --- a/packages/@uppy/react/src/useUppy.js +++ b/packages/@uppy/react/src/useUppy.js @@ -1,6 +1,9 @@ import { useEffect, useRef } from 'react' import { Uppy as UppyCore } from '@uppy/core' +/** + * @deprecated Initialize Uppy outside of the component or with `useState` and `useEffect` (see docs) + */ export default function useUppy (factory) { if (typeof factory !== 'function') { throw new TypeError('useUppy: expected a function that returns a new Uppy instance') diff --git a/website/src/docs/react-initializing.md b/website/src/docs/react-initializing.md deleted file mode 100644 index 220f50cf44..0000000000 --- a/website/src/docs/react-initializing.md +++ /dev/null @@ -1,63 +0,0 @@ ---- -title: "Initializing Uppy" -type: docs -module: "@uppy/react" -permalink: docs/react/initializing/ -alias: docs/react/initializing/ -order: 1 -category: "React" ---- - -When using Uppy’s React components, an Uppy instance must be passed in to the `uppy={}` prop from the outside. This Uppy instance must be initialized before passing it to the desired component, and be cleaned up using `uppy.close()` when you are done with it. - -## Functional Components - -Functional components are re-run on every render. This could lead to accidentally recreate a fresh Uppy instance every time, causing state to be reset and resources to be wasted. - -The `@uppy/react` package provides a hook `useUppy()` that can manage an Uppy instance’s lifetime for you. It will be created when your component is first rendered, and destroyed when your component unmounts. - -```js -import Uppy from '@uppy/core' -import React from 'react' -import Tus from '@uppy/tus' -import { DashboardModal, useUppy } from '@uppy/react' - -function MyComponent () { - const uppy = useUppy(() => { - return new Uppy() - .use(Tus, { endpoint: 'https://tusd.tusdemo.net/files' }) - }) - - return -} -``` - -Importantly, the `useUppy()` hook takes a _function_ that returns an Uppy instance. This way, the `useUppy()` hook can decide when to create it. Otherwise you would still be creating an unused Uppy instance on every render. - -## Class Components - -A common approach is to create an Uppy instance in your React component’s `constructor()` and destroy it in `componentWillUnmount()`. - -> ⚠ Uppy instances are stateful, so the same instance must be used across different renders. -> Do **NOT** initialize Uppy in a `render()` method! - -```js -import React from 'react' -import { DashboardModal } from '@uppy/react' - -class MyComponent extends React.Component { - constructor (props) { - super(props) - this.uppy = new Uppy() - .use(Transloadit, {}) - } - - componentWillUnmount () { - this.uppy.close({ reason: 'unmount' }) - } - - render () { - return - } -} -``` diff --git a/website/src/docs/react.md b/website/src/docs/react.md index 5141a5197f..b4f6659abc 100644 --- a/website/src/docs/react.md +++ b/website/src/docs/react.md @@ -19,10 +19,6 @@ Install from NPM: npm install @uppy/react ``` -## CSS - -Make sure to also include the necessary CSS files for each Uppy React component you are using. Follow links for individual components docs below for details on that. - ## Usage The components can be used with either [React][] or API-compatible alternatives such as [Preact][]. @@ -31,48 +27,55 @@ Instead of adding a UI plugin to an Uppy instance with `.use()`, the Uppy instan All other props are passed as options to the plugin. ```js -import React from 'react' +import React, { useEffect } from 'react' import Uppy from '@uppy/core' -import Tus from '@uppy/tus' -import { DragDrop } from '@uppy/react' - -const uppy = new Uppy({ - meta: { type: 'avatar' }, - restrictions: { maxNumberOfFiles: 1 }, - autoProceed: true, -}) - -uppy.use(Tus, { endpoint: '/upload' }) - -uppy.on('complete', (result) => { - const url = result.successful[0].uploadURL - store.dispatch({ - type: 'SET_USER_AVATAR_URL', - payload: { url }, - }) -}) - -const AvatarPicker = ({ currentAvatar }) => { - return ( -
- Current Avatar - -
- ) +import { Dashboard } from '@uppy/react' + +const uppy = new Uppy() + +function Component () { + useEffect(() => { + return () => { + uppy.close({ reason: 'unmount' }) + } + }, []) + + return } ``` +### Dynamic options + +```js +import React, { useState, useEffect } from 'react' +import Uppy from '@uppy/core' +import { Dashboard } from '@uppy/react' + +function Component ({ restrictions }) { + const [uppy, setUppy] = useState(() => new Uppy({ restrictions })) + + useEffect(() => { + // Change @uppy/core options + uppy.setOptions({ restrictions }) + + // Or change some plugin dynamically + // uppy.getPlugin('SomePlugin').setOptions({ /* options */ }) + + return () => { + uppy.close({ reason: 'unmount' }) + } + }, [uppy, restrictions]) + + return +} +``` + +## CSS + +Make sure to also include the necessary CSS files for each Uppy React component you are using. Follow links for individual components docs below for details on that. + +## Components + The following plugins are available as React component wrappers (you need to install each package separately): From 76fff179dcd6efe9df07a9b9c203d73a96d5eac7 Mon Sep 17 00:00:00 2001 From: Murderlon Date: Wed, 16 Nov 2022 14:45:00 -0300 Subject: [PATCH 2/6] Simplify dynamic example --- website/src/docs/react.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/website/src/docs/react.md b/website/src/docs/react.md index b4f6659abc..414cbb8fa7 100644 --- a/website/src/docs/react.md +++ b/website/src/docs/react.md @@ -51,20 +51,20 @@ import React, { useState, useEffect } from 'react' import Uppy from '@uppy/core' import { Dashboard } from '@uppy/react' -function Component ({ restrictions }) { - const [uppy, setUppy] = useState(() => new Uppy({ restrictions })) +const uppy = new Uppy() +function Component ({ restrictions }) { useEffect(() => { // Change @uppy/core options uppy.setOptions({ restrictions }) // Or change some plugin dynamically - // uppy.getPlugin('SomePlugin').setOptions({ /* options */ }) + uppy.getPlugin('SomePlugin').setOptions({ /* options */ }) return () => { uppy.close({ reason: 'unmount' }) } - }, [uppy, restrictions]) + }, [restrictions]) return } From dd9a1ed24baf3d0f3270b1391aa807377681c3cd Mon Sep 17 00:00:00 2001 From: Murderlon Date: Wed, 14 Dec 2022 10:51:38 +0100 Subject: [PATCH 3/6] Update docs --- website/src/docs/react.md | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/website/src/docs/react.md b/website/src/docs/react.md index 414cbb8fa7..3d042dd594 100644 --- a/website/src/docs/react.md +++ b/website/src/docs/react.md @@ -26,21 +26,18 @@ The components can be used with either [React][] or API-compatible alternatives Instead of adding a UI plugin to an Uppy instance with `.use()`, the Uppy instance can be passed into components as an `uppy` prop. All other props are passed as options to the plugin. +You have to pass the IDs of your `use`d plugins to the `plugins` array props so Dashboard knows it needs to render them. + ```js import React, { useEffect } from 'react' import Uppy from '@uppy/core' +import Webcam from '@uppy/webcam' import { Dashboard } from '@uppy/react' -const uppy = new Uppy() +const uppy = new Uppy().use(Webcam) function Component () { - useEffect(() => { - return () => { - uppy.close({ reason: 'unmount' }) - } - }, []) - - return + return } ``` @@ -53,18 +50,14 @@ import { Dashboard } from '@uppy/react' const uppy = new Uppy() -function Component ({ restrictions }) { +function Component ({ maxFileSize }) { useEffect(() => { // Change @uppy/core options - uppy.setOptions({ restrictions }) + uppy.setOptions({ restrictions: { maxFileSize } }) // Or change some plugin dynamically uppy.getPlugin('SomePlugin').setOptions({ /* options */ }) - - return () => { - uppy.close({ reason: 'unmount' }) - } - }, [restrictions]) + }, [maxFileSize]) return } From 1ad2e971bf9028cc6141436b7f2dcd4cbb2a5215 Mon Sep 17 00:00:00 2001 From: Murderlon Date: Mon, 19 Dec 2022 10:22:23 +0100 Subject: [PATCH 4/6] Apply feedback --- packages/@uppy/react/src/useUppy.d.ts | 2 +- packages/@uppy/react/src/useUppy.js | 2 +- website/src/docs/react.md | 33 +++++++-------------------- 3 files changed, 10 insertions(+), 27 deletions(-) diff --git a/packages/@uppy/react/src/useUppy.d.ts b/packages/@uppy/react/src/useUppy.d.ts index f106a560a9..6c6e1f2136 100644 --- a/packages/@uppy/react/src/useUppy.d.ts +++ b/packages/@uppy/react/src/useUppy.d.ts @@ -1,7 +1,7 @@ import type Uppy from '@uppy/core' /** - * @deprecated Initialize Uppy outside of the component or with `useState` and `useEffect` (see docs) + * @deprecated Initialize Uppy outside of the component. */ declare function useUppy(factory: () => Uppy): Uppy diff --git a/packages/@uppy/react/src/useUppy.js b/packages/@uppy/react/src/useUppy.js index 0822995bdf..3913833b37 100644 --- a/packages/@uppy/react/src/useUppy.js +++ b/packages/@uppy/react/src/useUppy.js @@ -2,7 +2,7 @@ import { useEffect, useRef } from 'react' import { Uppy as UppyCore } from '@uppy/core' /** - * @deprecated Initialize Uppy outside of the component or with `useState` and `useEffect` (see docs) + * @deprecated Initialize Uppy outside of the component. */ export default function useUppy (factory) { if (typeof factory !== 'function') { diff --git a/website/src/docs/react.md b/website/src/docs/react.md index 3d042dd594..fb04f1dcf4 100644 --- a/website/src/docs/react.md +++ b/website/src/docs/react.md @@ -21,12 +21,17 @@ npm install @uppy/react ## Usage +`@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][]. -Instead of adding a UI plugin to an Uppy instance with `.use()`, the Uppy instance can be passed into components as an `uppy` prop. -All other props are passed as options to the plugin. +A couple things to keep in mind when using Uppy with React: -You have to pass the IDs of your `use`d plugins to the `plugins` array props so Dashboard knows it needs to render them. +* Instead of adding a UI plugin to an Uppy instance with `.use()`, the Uppy instance can be passed into components as an `uppy` prop. +* All other props are passed as options to the plugin. +* The Uppy instance should **not** live inside the component but outside of it. +* You have to pass the IDs of your `use`d plugins to the `plugins` array props so Dashboard knows it needs to render them. + +Here is a basic example: ```js import React, { useEffect } from 'react' @@ -41,28 +46,6 @@ function Component () { } ``` -### Dynamic options - -```js -import React, { useState, useEffect } from 'react' -import Uppy from '@uppy/core' -import { Dashboard } from '@uppy/react' - -const uppy = new Uppy() - -function Component ({ maxFileSize }) { - useEffect(() => { - // Change @uppy/core options - uppy.setOptions({ restrictions: { maxFileSize } }) - - // Or change some plugin dynamically - uppy.getPlugin('SomePlugin').setOptions({ /* options */ }) - }, [maxFileSize]) - - return -} -``` - ## CSS Make sure to also include the necessary CSS files for each Uppy React component you are using. Follow links for individual components docs below for details on that. From a71bce304aa94bb6e7f8a9f3a278caa17fbbe012 Mon Sep 17 00:00:00 2001 From: Merlijn Vos Date: Fri, 23 Dec 2022 11:14:02 +0100 Subject: [PATCH 5/6] Apply suggestion Co-authored-by: Mikael Finstad --- website/src/docs/react.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/website/src/docs/react.md b/website/src/docs/react.md index fb04f1dcf4..965d5fa3e8 100644 --- a/website/src/docs/react.md +++ b/website/src/docs/react.md @@ -29,7 +29,8 @@ A couple things to keep in mind when using Uppy with React: * Instead of adding a UI plugin to an Uppy instance with `.use()`, the Uppy instance can be passed into components as an `uppy` prop. * All other props are passed as options to the plugin. * The Uppy instance should **not** live inside the component but outside of it. -* You have to pass the IDs of your `use`d plugins to the `plugins` array props so Dashboard knows it needs to render them. +* You have to pass the IDs of your `use`d plugins to the `plugins` array prop so Dashboard knows it needs to render them. +* An Uppy instance can’t be used by multiple components. Make sure you are using a unique Uppy instance per component. Here is a basic example: From cf57064e4355a2e311804b844219276b576dbacd Mon Sep 17 00:00:00 2001 From: Merlijn Vos Date: Fri, 23 Dec 2022 14:21:20 +0100 Subject: [PATCH 6/6] Fix lint error --- website/src/docs/react.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/src/docs/react.md b/website/src/docs/react.md index 965d5fa3e8..1cd6263f98 100644 --- a/website/src/docs/react.md +++ b/website/src/docs/react.md @@ -30,7 +30,7 @@ A couple things to keep in mind when using Uppy with React: * All other props are passed as options to the plugin. * The Uppy instance should **not** live inside the component but outside of it. * You have to pass the IDs of your `use`d plugins to the `plugins` array prop so Dashboard knows it needs to render them. -* An Uppy instance can’t be used by multiple components. Make sure you are using a unique Uppy instance per component. +* An Uppy instance can’t be used by more than one component. Make sure you are using a unique Uppy instance per component. Here is a basic example: