-
Notifications
You must be signed in to change notification settings - Fork 1.8k
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
Image: support ImageSource with headers #2442
base: master
Are you sure you want to change the base?
Conversation
This pull request is automatically built and testable in CodeSandbox. To see build info of the built libraries, click here or the icon next to each commit SHA. Latest deployment of this branch, based on commit 616975e:
|
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.
Leaving some notes on the code changes
There's a breaking change that might be introduced or reverted - it's regarding the onLoad
prop and the parameter structure used - I've opened a thread on the relevant source code chunk
packages/react-native-web/src/exports/Image/__tests__/__snapshots__/index-test.js.snap
Outdated
Show resolved
Hide resolved
packages/react-native-web/src/exports/Image/__tests__/index-test.js
Outdated
Show resolved
Hide resolved
It would have been a good idea to ask about this before writing the PR, as there are numerous other plans around Image. There's this PR for crossOrigin support #2207 This milestone https://github.com/necolas/react-native-web/milestone/18 And a parallel effort to support W3C props on Image facebook/react-native#34424 |
Hi @necolas This PR is following the original idea to support headers via XHR, though I've opted to use Overall I think the changes here are compatible with #2207 A big chunk of the changes comes from added tests The rest of the changes are small cleanups and moving existing logic - I can revert some of these namely If there are any problems, I'm happy to discuss and modify the PR |
Please resolve the conflicts with master |
There are no conflicts with There would be conflicts for the PR that happens to be merged last due to the changes to Since the other PR just moves the function without changing the logic, it might be easier to do the same after this PR is merged |
If you could rebase/squash your 20 commits into just a few, that would help too. Thanks |
27f7163
to
7ecabef
Compare
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.
Squashed existing commits to allow rebasing
packages/react-native-web/src/exports/Image/__tests__/index-test.js
Outdated
Show resolved
Hide resolved
7ecabef
to
8324905
Compare
This comment was marked as off-topic.
This comment was marked as off-topic.
8324905
to
2d82778
Compare
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.
PR Updated using an alternative strategy to load images with headers resulting in less changes overall
When a source
with headers is used, we use a (kind of) a HOC component that fetches the source
and then passes a local uri created with URL.createObjectURL
to the original Image component
nativeEvent.source = { | ||
uri: image.src, | ||
width: image.naturalWidth, | ||
height: image.naturalHeight | ||
}; |
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.
Attach source
to nativeEvent
so onLoad
matches the RN Image interface https://reactnative.dev/docs/image#onload
@necolas any chance you or a fellow maintainer can check out these changes? We're fine to wait since, as you mentioned before, you have many updates planned - we're just hoping to get a possible timeline when this could get reviewed. |
It looks like the author is still working on the patch. It needs unit tests and the suggestion to make changes to make testing easier makes sense to me. |
What's next for this PR? The PR in the fork had no new unit tests and this one hasn't been updated for 2 weeks |
I haven't synced my latest changes here, and I still need to write some unit tests |
8533f2d
to
081216d
Compare
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.
Ready for Review ✅
jest.useFakeTimers(); | ||
ImageLoader.load = jest.fn().mockImplementation((_, onLoad, onError) => { | ||
onLoad(); | ||
}); |
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.
Fake timers no longer needed to pass this test
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.
Actually the fake timers are breaking the (new) tests that use Promises
For some reason unless we remove all calls to jest.useFakeTimers()
- return waitFor(() => ...)
does not work
function raiseOnErrorEvent(uri, { onError, onLoadEnd }) { | ||
if (onError) { | ||
onError({ | ||
nativeEvent: { | ||
error: `Failed to load resource ${uri} (404)` | ||
} | ||
}); | ||
} | ||
if (onLoadEnd) onLoadEnd(); | ||
} |
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 was extracted for reuse out of the original Image component hook
(We reuse this in case loading with headers fails)
/** | ||
* This component handles specifically loading an image source with headers | ||
* default source is never loaded using headers | ||
*/ | ||
const ImageWithHeaders: ImageComponent = React.forwardRef((props, ref) => { | ||
// $FlowIgnore: This component would only be rendered when `source` matches `ImageSource` | ||
const nextSource: ImageSource = props.source; |
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.
Perhaps there's a way to declare ImageWithHeaders
as an Image
component where the source
prop is exactly type ImageSource
, but I don't know exactly how
I guess I need to declare ImageWithHeaderProp
type that spreads the default Image prop type but changes the source
. Should I do that?
export type ImageProps = {| | ||
...$Exact<ViewProps>, |
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 had Flow
errors after my changes
Following the error messages and suggested fixes led to these changes
type ImageBackgroundProps = { | ||
type ImageBackgroundProps = {| | ||
...ImageProps, | ||
imageRef?: any, | ||
imageStyle?: $PropertyType<ImageProps, 'style'>, | ||
style?: $PropertyType<ViewProps, 'style'> | ||
}; | ||
|}; |
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 had Flow
errors after my changes
Following the error messages and suggested fixes led to these changes
Hi, please could you rebase this. Now that 0.19 is done, the 0.20 release will be focused on Image changes. |
081216d
to
616975e
Compare
✅ Rebased |
}; | ||
|
||
return <BaseImage ref={ref} {...propsToPass} />; | ||
}); | ||
|
||
// $FlowIgnore: This is the correct type, but casting makes it unhappy since the variables aren't defined yet |
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 this old $FlowIgnore
is removed, there is a new type error:
Cannot assign React.forwardRef(...) to ImageWithStatics because property getSize is missing in AbstractComponent [1] but
exists in ImageStatics [2]. [incompatible-type]
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 think I've seen the original error the comment references at some point
Could it be the error was fixed by a flow version update, but now we have this other error?
Extend ImageLoader functionality to be able to work with image sources containing headers We preserve the existing strategy that works with image.src for cases where source is just an uri with no headers When sources contain headers we make a fetch request and then render a local url for the downloaded blob (URL.createObjectURL) Fix #1019 Close #2442
This PR was merged into the 0.20-dev branch #2508 |
Extend ImageLoader functionality to be able to work with image sources containing headers We preserve the existing strategy that works with image.src for cases where source is just an uri with no headers When sources contain headers we make a fetch request and then render a local url for the downloaded blob (URL.createObjectURL) Fix #1019 Fix #2268 Close #2442
Extend ImageLoader functionality to be able to work with image sources containing headers We preserve the existing strategy that works with image.src for cases where source is just an uri with no headers When sources contain headers we make a fetch request and then render a local url for the downloaded blob (URL.createObjectURL) Fix #1019 Fix #2268 Close #2442
Details
Extend
ImageLoader
functionality to be able to work with image sources containing headersWe preserve the existing strategy that works with
image.src
for cases wheresource
is just an
uri
with no headersWhen
source
contain headers we make afetch
request and then render a local url for thedownloaded blob (
URL.createObjectURL
)Fixed Issues
Test Strategy
Verify existing Image functionality has no regressions
npm run dev -w react-native-web
andnpm run dev -w react-native-web-examples
Image
: http://localhost:3000/imagemaster
branch. You can switch back and forth and verify the image are loading the same wayVerify Images with headers can be loaded
npm run dev -w react-native-web
andnpm run dev -w react-native-web-examples
Image
: http://localhost:3000/imagesourceWithHeaders
herepackages/react-native-web-examples/pages/image/index.js
and try to load images from a server that expects a GET request with a headerExample Project Screenshot
The code is also tested in a standalone project and it loads images with headers successfully