-
Notifications
You must be signed in to change notification settings - Fork 10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve React example #15
Conversation
Improve React example
@nd0ut, I do not have enough rights to add you as a reviewer 🐨 |
examples/react-uploader/src/mocks.ts
Outdated
...`, | ||
photos: [ | ||
{ | ||
uuid: 'e456f8cd-a717-4894-932d-e1d39e043e50', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will also reupload the images. Currently they are uploaded to my own account, if I recall correctly.
"@vitejs/plugin-react": "^3.1.0", | ||
"prop-types": "15.8.1", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For some reason, when I install deps of this project via npm, everything works fine.
But when I use yarn, Vite screams that it can not find prop-types for react-toggle.
So I decided simply install the dep to make sure that users won't get the same error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
react-toggle
has prop-types
listed in its peer dependencies, and yarn handles them more strictly
examples/react-uploader/src/types.ts
Outdated
@@ -0,0 +1,6 @@ | |||
export type File = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the latest 0.29.0 version, there is an OutputFileEntry
type exported that could be used there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now when I'm trying to use the data I have got from LR_DATA_OUTPUT
, TS screams that types are not compatible:
src/App.tsx:27:60 - error TS2345: Argument of type '{ uuid: string; name: string; size: number; isStored: boolean; isImage: boolean; mimeType: string; cdnUrl: string; s3Url: null; origin
alFilename: string; imageInfo: { dpi: number[]; width: number; format: string; ... 5 more ...; datetimeOriginal: null; }; ... 13 more ...; uploadProgress: number; }[]' is not assignable
to parameter of type 'OutputFileEntry[] | (() => OutputFileEntry[])'.
Type '{ uuid: string; name: string; size: number; isStored: boolean; isImage: boolean; mimeType: string; cdnUrl: string; s3Url: null; originalFilename: string; imageInfo: { dpi: number
[]; width: number; format: string; ... 5 more ...; datetimeOriginal: null; }; ... 13 more ...; uploadProgress: number; }[]' is not assignable to type 'OutputFileEntry[]'.
Type '{ uuid: string; name: string; size: number; isStored: boolean; isImage: boolean; mimeType: string; cdnUrl: string; s3Url: null; originalFilename: string; imageInfo: { dpi: numb
er[]; width: number; format: string; ... 5 more ...; datetimeOriginal: null; }; ... 13 more ...; uploadProgress: number; }' is not assignable to type 'OutputFileEntry'.
Type '{ uuid: string; name: string; size: number; isStored: boolean; isImage: boolean; mimeType: string; cdnUrl: string; s3Url: null; originalFilename: string; imageInfo: { dpi: nu
mber[]; width: number; format: string; ... 5 more ...; datetimeOriginal: null; }; ... 13 more ...; uploadProgress: number; }' is not assignable to type 'Partial<Omit<UploadcareFile, requ
iredFileInfoFields>>'.
The types of 'imageInfo.datetimeOriginal' are incompatible between these types.
Type 'null' is not assignable to type 'string'.
27 const [photos, setPhotos] = useState<FormType['photos']>(MOCK_DATA.photos);
imageInfo.datetimeOriginal
returned from the File Uploader is null
. But the types say it must be string
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pushed the changes anyway. See a6a08d6.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now when I'm trying to use the data I have got from LR_DATA_OUTPUT, TS screams that types are not compatible:
Got it. This is a bug inside upload-client. I'll fix it soon.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
<img | ||
className={st.previewImage} | ||
key={file.uuid} | ||
src={`https://ucarecdn.com/${file.uuid}/-/preview/-/resize/x200/`} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's use cdnUrlModifiers
here to build preview url (or cdnUrl
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When I upload a file, I get cdnUrlModifiers
as null
.
So I used cdnUrl
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, looks like a bug. I'll check it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As far as I understand, it returns null
when the uploaded image was not changed via editor. Which complies with types:
cdnUrlModifiers: string | null;
It may be fine, but due to null
I will have to check it prior to using in the URL template. So, I decided to use cdnUrl
instead.
...`, | ||
photos: [ | ||
{ | ||
uuid: 'add046ce-95e3-4454-bccd-65e3e648c472', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do you store all this stuff here? Isn't just uuid/url/name enough?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the list of mocks. I believe mocks should be designed to match the real data as much as they can.
Plus it provides data consistency. I use these mocks as an initial value for the state. Later I add data returned by File Uploader to the same state. It would be weird to have differently structured objects inside one state array.
Well, I could probably use only subset of the fields here, and extract the same subset from the objects of the array returned by File Uploader. I do no think this is a good idea though, due to two reasons:
-
This will increase the number of code lines of the logic. I'd like to leave as less as possible of them, to make the example more vivid / dry.
-
I believe that the real life example would be closer to “let's store everything this thing returns” rather than storing UUID only. Because you never know what data you will need tomorrow, and it's always easy to remove excessive chunks from your DB.
|
||
|
||
return ( | ||
<div className={st.root}> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's better to use uploadCollection.clearAll()
on lr-upload-ctx-provider
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
const handleUploadEvent = (e: CustomEvent<{ data: OutputFileEntry[] }>) => { | ||
if (e.detail?.data) { | ||
const newUploadedFiles = e.detail.data.filter(file => file.isUploaded && !files.find(f => f.uuid === file.uuid)); | ||
onChange([...files, ...newUploadedFiles]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do you call the onChange
within the LR_DATA_OUTPUT event? Wouldn't it be more appropriate to do this within LR_DONE_FLOW? As the 'done' click represents a sort of "commit transaction" action in the regular mode. When a modal is shown, there seems to be no need to update any outer UI. Perhaps it might be better to switch to the inline or minimal mode instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do you call the onChange within the LR_DATA_OUTPUT event?
My initial idea was to use LR_DATA_OUTPUT
, because it's easier this way.
LR_DONE_FLOW
returns nothing:
window.addEventListener('LR_DONE_FLOW', e => console.log(e));
{
"ctx": "my-uploader",
"data": undefined,
"type": "DONE_FLOW"
}
The documentation says nothing about the ways to force LR_DONE_FLOW
to return anything.
As far as I understand, it's intentional and not the lack of docs: https://github.com/uploadcare/blocks/blob/141f1edfdd6ccec7577b142927dfb219e8962d2a/abstract/UploaderBlock.js#L289-L296
If I triggered the onChange
on LR_DONE_FLOW
, then I would need to store the internal state of the uploader somehow. And I decided to get rid of this for the sake of brevity.
However, now I understand that this code is buggy. It filters files using UUID, which won't be changed when user applies transformations to an image. So, I've updated it: a108a84
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, LR_DONE_FLOW is intended to be just event without payload. But I'm sure, it's way more useful if it will provide files array as LR_DATA_OUTPUT do.
Great job! 🔥 Let's wait for this PR, update blocks to ensure the types are OK, and then we're good to go! |
@nd0ut, I've updated Blocks to v0.29.1 (caa5150). But now types are incompatible in a different place.
The log tries to say that this: does not match this: I believe it happens because types are trying to limit
Sooo, I've extracted Not sure it's a right way though. But anyway: 34265d9 |
It's possible to define {
dpi: [72, 72] as NonNullable<OutputFileEntry["imageInfo"]>["dpi"];
} or even better like this: {
photos: [
{
uuid: "add046ce-95e3-4454-bccd-65e3e648c472",
name: "arthurhumeau3xwdarHxHqIunsplash.jpg",
size: 1657550,
isStored: true,
isImage: true,
mimeType: "image/jpeg",
cdnUrl: "https://ucarecdn.com/add046ce-95e3-4454-bccd-65e3e648c472/",
s3Url: null,
originalFilename: "arthur-humeau-3xwdarHxHqI-unsplash.jpg",
imageInfo: {
dpi: [72, 72],
width: 2400,
format: "JPEG",
height: 3600,
sequence: false,
colorMode: "RGB",
orientation: null,
geoLocation: null,
datetimeOriginal: null,
},
videoInfo: null,
contentInfo: {
mime: {
mime: "image/jpeg",
type: "image",
subtype: "jpeg",
},
image: {
dpi: [72, 72],
width: 2400,
format: "JPEG",
height: 3600,
sequence: false,
colorMode: "RGB",
orientation: null,
geoLocation: null,
datetimeOriginal: null,
},
},
metadata: {},
s3Bucket: null,
cdnUrlModifiers: null,
// those properties are missing in your mocks so types are incompatible
validationErrorMessage: null,
file: null,
uploadError: null,
uploadProgress: 100,
isValid: false,
isUploaded: false,
fullPath: null,
externalUrl: null,
},
] as OutputFileEntry[];
} |
Hey there!
@tenebricosa and I have rewritten React example a bit. The main point is to make the example look like a part of a real world React app.
We're ready to your review :-)