Created
November 30, 2018 08:37
-
-
Save msandrini/7970c0ab448027aed539b085b5c9128b to your computer and use it in GitHub Desktop.
React component - Image tag with header auth
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* © Marcos Sandrini Lemos */ | |
import { Component, Fragment, createElement } from 'react'; | |
import PropTypes from 'prop-types'; | |
import axios from 'axios'; | |
const getMimeTypeFromExtension = (extension) => { | |
const allowedExtensions = ['jpeg', 'gif', 'png', 'webp']; | |
if (allowedExtensions.includes(extension)) return `image/${extension}`; | |
if (extension === 'jpg') return 'image/jpeg'; | |
if (extension === 'svg') return 'image/svg+xml'; | |
return 'image/*'; | |
}; | |
const transparentPixelImage = 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs%3D'; | |
export default class ImageWithAuth extends Component { | |
constructor() { | |
super(); | |
this.state = { | |
dataUrl: transparentPixelImage | |
}; | |
this.handleDataConverted = this.handleDataConverted.bind(this); | |
this.mimeType = null; | |
} | |
async componentDidMount() { | |
const { src } = this.props; | |
/* get image extension to be able to get the mime type */ | |
const imageSrcChunks = src.split('.'); | |
const extension = imageSrcChunks[imageSrcChunks.length - 1]; | |
const headers = this.getHeaders(extension); | |
/* with headers set, prepare to make call */ | |
const requestOptions = { headers, responseType: 'blob' }; | |
this.setState({ isLoading: true }); | |
/* make the call */ | |
const { status, data: binaryData } = await axios.get(src, requestOptions); | |
/* if call returns OK, proceed into converting the image data */ | |
if (status === 200) this.putBinaryDataIntoDataUrl(binaryData); | |
this.setState({ isLoading: false }); | |
} | |
getHeaders(extension) { | |
const { authToken } = this.props; | |
this.mimeType = getMimeTypeFromExtension(extension); | |
return { | |
Authorization: authToken, | |
'Content-Type': mimeType | |
}; | |
} | |
putBinaryDataIntoDataUrl(binary) { | |
/* convert image data from binary into dataURL using FileReader */ | |
const reader = new FileReader(); | |
const fileBlob = new Blob([binary], { type: this.mimeType }); | |
/* when conversion is finished (load event), puts dataURL into the state */ | |
reader.onload = this.handleDataConverted; | |
reader.readAsDataURL(fileBlob); | |
} | |
handleDataConverted(event) { | |
this.setState({ dataUrl: event.target.result }); | |
} | |
render() { | |
const { altText, spinner } = this.props; | |
const { dataUrl, isLoading } = this.state; | |
return ( | |
<Fragment> | |
{isLoading && spinner}, | |
<img src={dataUrl} alt={altText} /> | |
</Fragment> | |
); | |
} | |
} | |
ImageWithAuth.propTypes = { | |
src: PropTypes.string.isRequired, | |
altText: PropTypes.string, | |
spinner: PropTypes.node, | |
authToken: PropTypes.string | |
}; | |
ImageWithAuth.defaultProps = { | |
altText: '', | |
spinner: null, | |
authToken: '' | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment