react.mdx 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. ---
  2. slug: /react
  3. ---
  4. import Tabs from '@theme/Tabs';
  5. import TabItem from '@theme/TabItem';
  6. # React
  7. [React][] components for the Uppy UI plugins and a `useUppyState` hook.
  8. ## Install
  9. <Tabs>
  10. <TabItem value="npm" label="NPM" default>
  11. ```shell
  12. npm install @uppy/react
  13. ```
  14. </TabItem>
  15. <TabItem value="yarn" label="Yarn">
  16. ```shell
  17. yarn add @uppy/react
  18. ```
  19. </TabItem>
  20. </Tabs>
  21. :::note
  22. You also need to install the UI plugin you want to use. For instance,
  23. `@uppy/dashboard`.
  24. :::
  25. ## Use
  26. `@uppy/react` exposes component wrappers for `Dashboard`, `DragDrop`, and all
  27. other UI elements. The components can be used with either [React][] or
  28. API-compatible alternatives such as [Preact][].
  29. :::caution
  30. If you find yourself writing many instances of `useState` and `useEffect` to
  31. achieve something with Uppy in React, you are most likely breaking React best
  32. practices. Consider reading
  33. “[You Might Not Need an Effect](https://react.dev/learn/you-might-not-need-an-effect)”
  34. and looking at our examples below.
  35. :::
  36. ### Components
  37. The following components are exported from `@uppy/react`:
  38. - `<Dashboard />` renders [`@uppy/dashboard`](/docs/dashboard)
  39. - `<DragDrop />` renders [`@uppy/drag-drop`](/docs/drag-drop)
  40. - `<ProgressBar />` renders [`@uppy/progress-bar`](/docs/progress-bar)
  41. - `<StatusBar />` renders [`@uppy/status-bar`](/docs/status-bar)
  42. {/* prettier-ignore */}
  43. {/* Commented out until the hook is live
  44. ### Hooks
  45. `useUppyState(uppy, selector)`
  46. Use this hook when you need to access Uppy’s state reactively. Most of the
  47. times, this is needed if you are building a custom UI for Uppy in React.
  48. ```js
  49. // IMPORTANT: passing an initializer function to prevent Uppy from being reinstantiated on every render.
  50. const [uppy] = useState(() => new Uppy());
  51. const files = useUppyState(uppy, (state) => state.files);
  52. const totalProgress = useUppyState(uppy, (state) => state.totalProgress);
  53. // We can also get specific plugin state.
  54. // Note that the value on `plugins` depends on the `id` of the plugin.
  55. const metaFields = useUppyState(
  56. uppy,
  57. (state) => state.plugins?.Dashboard?.metaFields,
  58. );
  59. ```
  60. You can see all the values you can access on the
  61. [`State`](https://github.com/transloadit/uppy/blob/main/packages/%40uppy/core/types/index.d.ts#L190)
  62. type. If you are accessing plugin state, you would have to look at the types of
  63. the plugin.
  64. \*/}
  65. ## Examples
  66. ### Example: basic component
  67. Here we have a basic component which ties Uppy’s state to the component. This
  68. means you can render multiple instances. But be aware that as your component
  69. unmounts, for instance because the user navigates to a different page, Uppy’s
  70. state will be lost and uploads will stop.
  71. :::note
  72. If you render multiple instances of Uppy, make sure to give each instance a
  73. unique `id`.
  74. :::
  75. ```js
  76. import React, { useEffect, useState } from 'react';
  77. import Uppy from '@uppy/core';
  78. import Webcam from '@uppy/webcam';
  79. import { Dashboard } from '@uppy/react';
  80. import '@uppy/core/dist/style.min.css';
  81. import '@uppy/dashboard/dist/style.min.css';
  82. import '@uppy/webcam/dist/style.min.css';
  83. function Component() {
  84. // IMPORTANT: passing an initializer function to prevent Uppy from being reinstantiated on every render.
  85. const [uppy] = useState(() => new Uppy().use(Webcam));
  86. return <Dashboard uppy={uppy} plugins={['Webcam']} />;
  87. }
  88. ```
  89. ### Example: keep Uppy state and uploads while navigating between pages
  90. When you want Uppy’s state to persist and keep uploads running between pages,
  91. you can
  92. [lift the state up](https://react.dev/learn/sharing-state-between-components#lifting-state-up-by-example).
  93. ```js
  94. import React, { useState, useEffect } from 'react';
  95. import Uppy from '@uppy/core';
  96. import { Dashboard } from '@uppy/react';
  97. function Page1() {
  98. // ...
  99. }
  100. function Page2({ uppy }) {
  101. return (
  102. <>
  103. <p>{totalProgress}</p>
  104. <Dashboard id="dashboard" uppy={uppy} />
  105. </>
  106. );
  107. }
  108. export default function App() {
  109. // keeping the uppy instance alive above the pages the user can switch during uploading
  110. const [uppy] = useState(() => new Uppy());
  111. return (
  112. // Add your router here
  113. <>
  114. <Page1 />
  115. <Page2 uppy={uppy} />
  116. </>
  117. );
  118. }
  119. ```
  120. ### Example: updating Uppy’s options dynamically based on props
  121. ```js
  122. // ...
  123. function Component(props) {
  124. // IMPORTANT: passing an initializer function to prevent the state from recreating.
  125. const [uppy] = useState(() => new Uppy().use(Webcam));
  126. useEffect(() => {
  127. uppy.setOptions({ restrictions: props.restrictions });
  128. }, [props.restrictions]);
  129. useEffect(() => {
  130. uppy.getPlugin('Webcam').setOptions({ modes: props.webcamModes });
  131. }, [props.webcamModes]);
  132. return <Dashboard uppy={uppy} plugins={['Webcam']} />;
  133. }
  134. ```
  135. ### Example: dynamic params and signature for Transloadit
  136. When you go to production always make sure to set the `signature`. **Not using
  137. [Signature Authentication](https://transloadit.com/docs/topics/signature-authentication/)
  138. can be a security risk**. Signature Authentication is a security measure that
  139. can prevent outsiders from tampering with your Assembly Instructions.
  140. Generating a signature should be done on the server to avoid leaking secrets. In
  141. React, this could get awkward with a `fetch` in a `useEffect` and setting it to
  142. `useState`. Instead, it’s easier to use the
  143. [`assemblyOptions`](/docs/transloadit#assemblyoptions) option to `fetch` the
  144. params.
  145. ```js
  146. // ...
  147. function createUppy(userId) {
  148. return new Uppy({ meta: { userId } }).use(Transloadit, {
  149. async assemblyOptions(file) {
  150. // You can send meta data along for use in your template.
  151. // https://transloadit.com/docs/topics/assembly-instructions/#form-fields-in-instructions
  152. const body = JSON.stringify({ userId: file.meta.userId });
  153. const res = await fetch('/transloadit-params', { method: 'POST', body });
  154. return response.json();
  155. },
  156. });
  157. }
  158. function Component({ userId }) {
  159. // IMPORTANT: passing an initializer function to prevent Uppy from being reinstantiated on every render.
  160. const [uppy] = useState(() => createUppy(userId));
  161. useEffect(() => {
  162. if (userId) {
  163. // Adding to global `meta` will add it to every file.
  164. uppy.setOptions({ meta: { userId } });
  165. }
  166. }, [uppy, userId]);
  167. }
  168. ```
  169. [react]: https://facebook.github.io/react
  170. [preact]: https://preactjs.com/