React class component convert to functional component (Antdesign) - reactjs

I'm new to React and I want to use Antdesign for image upload, but the component class component given in ant design's site. How can I convert the code below into a functional component?
in what way can i do this? Or is there any online tool that can do this?
here is my code :
function getBase64(img, callback) {
const reader = new FileReader();
reader.addEventListener('load', () => callback(reader.result));
reader.readAsDataURL(img);
}
function beforeUpload(file) {
const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png';
if (!isJpgOrPng) {
message.error('You can only upload JPG/PNG file!');
}
const isLt2M = file.size / 1024 / 1024 < 2;
if (!isLt2M) {
message.error('Image must smaller than 2MB!');
}
return isJpgOrPng && isLt2M;
}
class Avatar extends React.Component {
state = {
loading: false,
};
handleChange = info => {
if (info.file.status === 'uploading') {
this.setState({ loading: true });
return;
}
if (info.file.status === 'done') {
// Get this url from response in real world.
getBase64(info.file.originFileObj, imageUrl =>
this.setState({
imageUrl,
loading: false,
}),
);
}
};
render() {
const { loading, imageUrl } = this.state;
const uploadButton = (
<div>
{loading ? <LoadingOutlined /> : <PlusOutlined />}
<div style={{ marginTop: 8 }}>Upload</div>
</div>
);
return (
<Upload
name="avatar"
listType="picture-card"
className="avatar-uploader"
showUploadList={false}
action="https://www.mocky.io/v2/5cc8019d300000980a055e76"
beforeUpload={beforeUpload}
onChange={this.handleChange}
>
{imageUrl ? <img src={imageUrl} alt="avatar" style={{ width: '100%' }} /> : uploadButton}
</Upload>
);
}
}
ReactDOM.render(<Avatar />, mountNode);

You will need to replace your class with a function that returns a JSX element.
You'll need to refactor your state to use the useState hook: https://reactjs.org/docs/hooks-state.html
DigitalOcean has a nice guide here: https://www.digitalocean.com/community/tutorials/five-ways-to-convert-react-class-components-to-functional-components-with-react-hooks
It will end up looking something like the following:
function getBase64(img, callback) {
const reader = new FileReader();
reader.addEventListener("load", () => callback(reader.result));
reader.readAsDataURL(img);
}
function beforeUpload(file) {
const isJpgOrPng = file.type === "image/jpeg" || file.type === "image/png";
if (!isJpgOrPng) {
message.error("You can only upload JPG/PNG file!");
}
const isLt2M = file.size / 1024 / 1024 < 2;
if (!isLt2M) {
message.error("Image must smaller than 2MB!");
}
return isJpgOrPng && isLt2M;
}
function Avatar() {
const [imageUrl, setImageUrl] = useState(null);
const [loading, setLoading] = useState(false);
const handleChange = (info) => {
if (info.file.status === "uploading") {
setLoading(true)
return;
}
if (info.file.status === "done") {
// Get this url from response in real world.
getBase64(info.file.originFileObj, (imageUrl) => {
setImageUrl(imageUrl);
setLoading(false);
});
}
};
const uploadButton = (
<div>
{loading ? <LoadingOutlined /> : <PlusOutlined />}
<div style={{ marginTop: 8 }}>Upload</div>
</div>
);
return (
<Upload
name="avatar"
listType="picture-card"
className="avatar-uploader"
showUploadList={false}
action="https://www.mocky.io/v2/5cc8019d300000980a055e76"
beforeUpload={beforeUpload}
onChange={handleChange}
>
{imageUrl ? (
<img src={imageUrl} alt="avatar" style={{ width: "100%" }} />
) : (
uploadButton
)}
</Upload>
);
};

Related

Using ant design uploader to show a profile picture

I am using the ant design uploader to show the user profile picture in the dashboard page, In case a picture is not there in the database, then it must show the default upload button instead.
Below is an example ant design provides, how would I implement the login I've mentioned above.
import { Upload, message } from 'antd';
import { LoadingOutlined, PlusOutlined } from '#ant-design/icons';
function getBase64(img, callback) {
const reader = new FileReader();
reader.addEventListener('load', () => callback(reader.result));
reader.readAsDataURL(img);
}
function beforeUpload(file) {
const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png';
if (!isJpgOrPng) {
message.error('You can only upload JPG/PNG file!');
}
const isLt2M = file.size / 1024 / 1024 < 2;
if (!isLt2M) {
message.error('Image must smaller than 2MB!');
}
return isJpgOrPng && isLt2M;
}
class Avatar extends React.Component {
state = {
loading: false,
};
handleChange = info => {
if (info.file.status === 'uploading') {
this.setState({ loading: true });
return;
}
if (info.file.status === 'done') {
// Get this url from response in real world.
getBase64(info.file.originFileObj, imageUrl =>
this.setState({
imageUrl,
loading: false,
}),
);
}
};
render() {
const { loading, imageUrl } = this.state;
const uploadButton = (
<div>
{loading ? <LoadingOutlined /> : <PlusOutlined />}
<div style={{ marginTop: 8 }}>Upload</div>
</div>
);
return (
<Upload
name="avatar"
listType="picture-card"
className="avatar-uploader"
showUploadList={false}
action="https://www.mocky.io/v2/5cc8019d300000980a055e76"
beforeUpload={beforeUpload}
onChange={this.handleChange}
>
{imageUrl ? <img src={imageUrl} alt="avatar" style={{ width: '100%' }} /> : uploadButton}
</Upload>
);
}
}
ReactDOM.render(<Avatar />, mountNode);

How to create a unique instance of an object

I fire an onclick called onEditScheduleClick this sets an object which is all fine, however when I click on an edit button on a different row data is overwritten in the props.setScheduleFieldData.
when I click the editButton the 70 will display too 70 and it will have the same dataabase name as ID 156.
As you can see, when I hit the edit button the data is logged fine. I am thinking I may need to create a unique instance for each row? Could someone help me out please!
Schedules
const schedules = () => {
const autoComplete = useContext(AutoCompleteContext)
const snackbar = useContext(SnackbarContext)
const loading = useContext(LoadingContext)
const user = useContext(UserContext)
const [scheduleData, setScheduleData] = useState([])
const [showScheduleModal, setShowScheduleModal] = useState(false)
const [scheduleFieldData, setScheduleFieldData] = useState({})
const [database, setDatabase] = useState('')
useEffect(() => {
async function onLoadScheduleData(){
loading.setLoading(true)
const [results, projectResults,databaseAutoCompleteResults] = await Promise.all([
get('get_testing_schedules', user.user),
get('get_projects_autocomplete/b', user.user),
get('get_databases_autocomplete/a', user.user)
])
autoComplete.setProjectsAutoComplete(projectResults)
autoComplete.setDatabasesAutoComplete(databaseAutoCompleteResults)
setScheduleData(results.data)
loading.setLoading(false)
}
onLoadScheduleData()
}, [])
const sortedScheduleData = [].concat(scheduleData)
.sort((a, b) => a.id < b.id ? 1 : -1)
const showModal = () => {
setShowScheduleModal(true)
setScheduleFieldData({})
}
const onCloseScheduleModal = () => setShowScheduleModal(false)
const onScheduleFieldUpdate = (e, valueFromAutoComplete, nameFromAutoComplete) => {
const name = nameFromAutoComplete ? nameFromAutoComplete
: e.target.name || e.target.getAttribute('name')
const value = valueFromAutoComplete ? valueFromAutoComplete.map(val => val.value).join(',')
: e.target.innerText ? e.target.innerText
: e.target.value
setScheduleFieldData({...scheduleFieldData, ...{[name]: value}})
console.log(name)
}
const onDatabaseSelect = async (e, value) => {
autoComplete.onDatabaseAutoCompleteFieldUpdate(e)
const name = e.target.getAttribute('name')
console.log(name)
setDatabase(value)
setScheduleFieldData({...scheduleFieldData, ...{[name]: value}})
}
console.log(scheduleFieldData, 'scheduleFieldData');
const onSubmitTestingScheduleClick = async () => {
loading.setLoading(true)
const results = await verifiedPost('post_testing_schedule', scheduleFieldData, user.user)
if (results.status === 0) {
setShowScheduleModal(false)
setScheduleFieldData({})
setScheduleData(results.data)
} else if(results.status >= 20 && results.status <= 30) {
user.setSessionTokenMatches(false)
}
snackbar.statusCheck(results)
loading.setLoading(false)
}
return (!scheduleData ? null :
<PageWrapper title='Schedules'>
<div style={{marginBottom: '20px'}}>
<Button
onClick={showModal}
className='Button Dark Main'
text='CREATE SCHEDULE'
/>
</div>
<div className='Card'>
<div className='TableTopbar ScheduleGrid'>
<div>ID</div>
<div>Interval</div>
<div>Project ID</div>
<div>Database</div>
<div>Create Timestamp</div>
<div>Create User Id</div>
<div>Edit</div>
</div>
{sortedScheduleData.map(schedule =>
<ScheduleDataRow
key={schedule.id}
schedule={schedule}
setScheduleData={setScheduleData}
onScheduleFieldUpdate={onScheduleFieldUpdate}
setScheduleFieldData={setScheduleFieldData}
scheduleFieldData={scheduleFieldData}
onDatabaseSelect={onDatabaseSelect}
/>
)}
</div>
<ScheduleModal
showScheduleModal={showScheduleModal}
onCloseScheduleModal={onCloseScheduleModal}
onScheduleFieldUpdate={onScheduleFieldUpdate}
scheduleFieldData={scheduleFieldData}
onSubmitTestingScheduleClick={onSubmitTestingScheduleClick}
scheduleFieldData={scheduleFieldData}
// onFieldUpdate={onFieldUpdate}
onDatabaseSelect={onDatabaseSelect}
database={database}
/>
</PageWrapper>
)
}
export default schedules
ScheduleDataRow:
const scheduleDataRow = props => {
const testing = useContext(TestingFrameworkContext)
const autoComplete = useContext(AutoCompleteContext)
const snackbar = useContext(SnackbarContext)
const loading = useContext(LoadingContext)
const user = useContext(UserContext)
const [usageMode, setUsageMode] = useState('Read')
const onEditScheduleClick = () => {
props.setScheduleFieldData({
'id': props.schedule.id,
'interval': props.schedule.interval,
'project_id': props.schedule.project_id,
'database': props.schedule.database.toString(),
})
setUsageMode('Edit')
}
const onSubmitTestingScheduleClick = async () => {
loading.setLoading(true)
const results = await verifiedPost('post_testing_schedule', props.scheduleFieldData, user.user)
if (results.status === 0) {
props.setScheduleData(results.data)
setUsageMode('Read')
} else if(results.status >= 20 && results.status <= 30) {
user.setSessionTokenMatches(false)
}
snackbar.statusCheck(results)
loading.setLoading(false)
}
const onCancelEditScheduleClick = () => setUsageMode('Read')
const getPartialDatabase = (database) => {
const split = database.split('::')
return split[split.length - 1]
}
return (
<div className='Table ScheduleGrid'>
{usageMode === 'Read' ?
<React.Fragment>
<div>{props.schedule.id}</div>
<div>{props.schedule.interval}</div>
<div>{props.schedule.project_id}</div>
<div>{getPartialDatabase(props.schedule.database)}</div>
<div>{props.schedule.create_timestamp}</div>
<div>{props.schedule.create_user_id}</div>
<div>
<EditIcon
style={{padding: '2px', width: '0.8em', height: '0.8em', marginRight: '5px'}}
className='CircleButton'
onClick={onEditScheduleClick}
/>
</div>
</React.Fragment>
:
<React.Fragment>
<div>{props.schedule.id}</div>
{configs.map((config, k) => {
const Field = config.field
return (
<div key={config.name} className='Main'>
<Field
uniqueIdentifier={config.name}
placeholder={config.label}
name={config.name}
uniqueIdentifier={k}
onChange={props.onScheduleFieldUpdate}
onSelect={props.onScheduleFieldUpdate}
onAutoCompleteOnChange={autoComplete.onProjectAutoCompleteFieldUpdate}
options={config.name === 'project_id' ? autoComplete.projectsAutoComplete : config.name === 'database' ? autoComplete.databasesAutoComplete : config.options}
value={props.scheduleFieldData[config.name]}
initialValues={
props.scheduleFieldData[config.name].split(',').filter(x => x).map(x => ({label: x, value: x}))
}
/>
</div>
)
})}
<div><AutoCompleteSingle
name='database'
label='Database'
options={autoComplete.databasesAutoComplete}
onChange={autoComplete.onDatabaseAutoCompleteFieldUpdate}
onSelect={props.onDatabaseSelect}
initialValue={props.scheduleFieldData['database']}
uniqueIdentifier={1}
triggerOnSelectOnBackspace
/></div>
<div>{props.schedule.create_timestamp}</div>
<div>{props.schedule.create_user_id}</div>
<div style={{display: 'flex', alignItems: 'flex-start'}}>
<div>
<Button
style={{marginRight: '10px'}}
text='Submit'
disabled={false}
className='Button Dark Main'
onClick={onSubmitTestingScheduleClick}
/>
</div>
<div>
<Button
text='Cancel'
className='Button Dark Main'
onClick={onCancelEditScheduleClick}
/>
</div>
</div>
</React.Fragment>
}
</div>
)
}
scheduleDataRow.propTypes = {
schedule: PropTypes.object,
setScheduleData: PropTypes.func
}
export default scheduleDataRow

I need to click twice before data returns in console properly

In this react component, I want to render the data into my console when the 'TO FROM SELECTED UNITS' button is clicked by the user, but the button has to be pressed twice for the data to show in the console.
Please ignore:
It looks like your post is mostly code; please add some more details.
It looks like your post is mostly code; please add some more details.
It looks like your post is mostly code; please add some more details.
It looks like your post is mostly code; please add some more details.
Here is my code:
const unitTests = props => {
const autoComplete = useContext(AutoCompleteContext)
const loading = useContext(LoadingContext)
const snackbar = useContext(SnackbarContext)
const user = useContext(UserContext)
const query = new URLSearchParams(props.location.search)
const targetObjectFromURL = query.get('object')
const cookies = new Cookies()
const [unitTestsData, setUnitTestsData] = useState(null)
const [database, setDatabase] = useState('')
const [targetObject, setTargetObject] = useState(null)
const [unitTestsMode, setUnitTestsMode] = useState('Object')
const [AddRemoveDatabaseChanges, setAddRemoveDatabaseChanges] = useState(null)
const [AddRemoveDatabaseMode, setAddRemoveDatabaseMode] = useState('ADD')
console.log(unitTestsData);
useEffect(() => {
async function onLoadUnitTests() {
loading.setLoading(true)
const [objectsAutoCompleteResults, databaseAutoCompleteResults] = await Promise.all([
get('get_objects_autocomplete/all/all/b', user.user),
get('get_databases_autocomplete/a', user.user)
])
autoComplete.setObjectsAutoComplete(objectsAutoCompleteResults)
autoComplete.setDatabasesAutoComplete(databaseAutoCompleteResults)
if(targetObjectFromURL) setTargetObject(targetObjectFromURL)
else if(cookies.get('table')) setTargetObject(cookies.get('table'))
loading.setLoading(false)
}
onLoadUnitTests()
}, [])
useEffect(() => {
async function getUnitTests() {
loading.setLoading(true)
const optionalParams = unitTestsMode === 'Object'
? `?type=object&target=${targetObject}`
: `?type=database&target=${database}`
const url = `get_unit_tests${optionalParams}`
const results = await verifiedGet(url, user.user)
if(results.status === 0) {
setUnitTestsData(results.data)
} else if(results.status >= 20 && results.status <= 30) {
snackbar.statusCheck(results)
user.setSessionTokenMatches(false)
} else snackbar.statusCheck(results)
loading.setLoading(false)
}
if(targetObject || database) getUnitTests()
}, [targetObject,database])
const onObjectSelect = (e, value) => {
props.history.push(`/unittests?object=${value}`)
setTargetObject(value)
cookies.set('table', value, { path: '/'})
}
const onNewTestCaseClick = () => {
props.history.push(`/createtest?object=${targetObject}`)
}
const onDatabaseSelect = (e, value) => setDatabase(value)
const onChangeUnitTestsMode = (e) => setUnitTestsMode(e.target.getAttribute('value'))
const onChangeAddRemoveMode = (e) => setAddRemoveDatabaseMode(e.target.getAttribute('value'))
console.log(AddRemoveDatabaseMode);
const addtoproduction = () => {
let databaseChanges = unitTestsData.map(tests => {
return {
"unit_test_id": tests.unit_test_template_id,
"databases": tests.databases
}
})
setAddRemoveDatabaseChanges(databaseChanges)
if(AddRemoveDatabaseChanges != null && AddRemoveDatabaseMode === 'ADD'){
console.log('added data', AddRemoveDatabaseChanges);
} else if (AddRemoveDatabaseChanges != null && AddRemoveDatabaseMode === 'REMOVE') {
console.log('removed data', AddRemoveDatabaseChanges )
}
}
return (
<PageWrapper title='View Unit Tests'>
<div className='Main UnitTestsAutoCompleteWrapper' style={{display: 'flex', justifyContent: 'center', alignItems: 'center'}}>
<div style={{width: '30%', marginRight: '10px'}}>
<DropdownSingle
options={['Object', 'Database']}
value='Object'
name='Search unit tests'
onChange={onChangeUnitTestsMode}
/>
</div>
{unitTestsMode === 'Object' ?
<div>
<AutoCompleteSingle
name='Table'
label='Table'
options={autoComplete.objectsAutoComplete}
onChange={autoComplete.onObjectAutoCompleteFieldUpdate}
onSelect={onObjectSelect}
uniqueIdentifier={0}
initialValue={targetObject}
/>
</div> :
<div style={{display: 'flex', justifyContent: 'space-between' }}>
<div style={{width: '100%'}}>
<DropdownSingle
options={['ADD', 'REMOVE']}
value='ADD'
name='Search unit tests'
onChange={onChangeAddRemoveMode}
/>
</div>
<AutoCompleteSingle
name='Database'
label='Database'
options={autoComplete.databasesAutoComplete}
onChange={autoComplete.onDatabaseAutoCompleteFieldUpdate}
onSelect={onDatabaseSelect}
uniqueIdentifier={1}
style={{width: '1000%'}}
/>
<div>
<Button
text='TO/FROM SELECTED UNIT TESTS'
onClick={addtoproduction}
/>
</div>
</div>
}
</div>
{!unitTestsData ? null :
!unitTestsData.length ?
<div>
This table has no associated unit tests
<div style={{marginTop: '20px'}}>
<Button
text='New Test Case'
icon={<AddIcon className='ButtonIcon' />}
onClick={onNewTestCaseClick}
className='Button Dark Main'
style={{width: '200px'}}
/>
</div>
</div>
:
unitTestsMode === 'Object' ?
<UnitTestsObjectView unitTestsData={unitTestsData}/>
: <UnitTestsDatabaseView unitTestsData={unitTestsData} />
}
{!targetObject ? null :
<div style={{position: 'fixed', bottom: '80px', right: '40px'}}>
<Button
text='New Test Case'
icon={<AddIcon className='ButtonIcon' />}
onClick={onNewTestCaseClick}
className='Button Dark Main'
/>
</div>
}
</PageWrapper>
)
}
export default withRouter(unitTests)

How to pass usestate data to function

I am trying to pass my unitTestData into the addtoproduction function however the console log is returning with null and I am not to sure why. The addtoproduction function is highlighted to asteriks
const unitTests = props => {
const autoComplete = useContext(AutoCompleteContext)
const loading = useContext(LoadingContext)
const snackbar = useContext(SnackbarContext)
const user = useContext(UserContext)
const query = new URLSearchParams(props.location.search)
const targetObjectFromURL = query.get('object')
const cookies = new Cookies()
const [unitTestsData, setUnitTestsData] = useState(null)
const [database, setDatabase] = useState('')
const [targetObject, setTargetObject] = useState(null)
const [unitTestsMode, setUnitTestsMode] = useState('Object')
useEffect(() => {
async function onLoadUnitTests() {
loading.setLoading(true)
const [objectsAutoCompleteResults, databaseAutoCompleteResults] = await Promise.all([
get('get_objects_autocomplete/all/all/b', user.user),
get('get_databases_autocomplete/a', user.user)
])
autoComplete.setObjectsAutoComplete(objectsAutoCompleteResults)
autoComplete.setDatabasesAutoComplete(databaseAutoCompleteResults)
if(targetObjectFromURL) setTargetObject(targetObjectFromURL)
else if(cookies.get('table')) setTargetObject(cookies.get('table'))
loading.setLoading(false)
}
onLoadUnitTests()
}, [])
useEffect(() => {
async function getUnitTests() {
loading.setLoading(true)
const optionalParams = unitTestsMode === 'Object'
? `?type=object&target=${targetObject}`
: `?type=database&target=${database}`
const url = `get_unit_tests${optionalParams}`
const results = await verifiedGet(url, user.user)
if(results.status === 0) {
setUnitTestsData(results.data)
} else if(results.status >= 20 && results.status <= 30) {
snackbar.statusCheck(results)
user.setSessionTokenMatches(false)
} else snackbar.statusCheck(results)
loading.setLoading(false)
}
if(targetObject || database) getUnitTests()
}, [targetObject,database])
const onObjectSelect = (e, value) => {
props.history.push(`/unittests?object=${value}`)
setTargetObject(value)
cookies.set('table', value, { path: '/'})
}
const onNewTestCaseClick = () => {
props.history.push(`/createtest?object=${targetObject}`)
}
const onDatabaseSelect = (e, value) => setDatabase(value)
const onChangeUnitTestsMode = (e) => setUnitTestsMode(e.target.getAttribute('value'))
** const addtoproduction = () => {
console.log(unitTestsData)
}**
return (
<PageWrapper title='View Unit Tests'>
<div className='Main UnitTestsAutoCompleteWrapper' style={{display: 'flex', justifyContent: 'center', alignItems: 'center'}}>
<div style={{width: '30%', marginRight: '10px'}}>
<DropdownSingle
options={['Object', 'Database']}
value='Object'
name='Search unit tests'
onChange={onChangeUnitTestsMode}
/>
</div>
{unitTestsMode === 'Object' ?
<div>
<AutoCompleteSingle
name='Table'
label='Table'
options={autoComplete.objectsAutoComplete}
onChange={autoComplete.onObjectAutoCompleteFieldUpdate}
onSelect={onObjectSelect}
uniqueIdentifier={0}
initialValue={targetObject}
/>
</div> :
<div>
<AutoCompleteSingle
name='Database'
label='Database'
options={autoComplete.databasesAutoComplete}
onChange={autoComplete.onDatabaseAutoCompleteFieldUpdate}
onSelect={onDatabaseSelect}
uniqueIdentifier={1}
/>
<div>
<Button onClick={addtoproduction} />
</div>
</div>
}
</div>
{!unitTestsData ? null :
!unitTestsData.length ?
<div>
This table has no associated unit tests
<div style={{marginTop: '20px'}}>
<Button
text='New Test Case'
icon={<AddIcon className='ButtonIcon' />}
onClick={onNewTestCaseClick}
className='Button Dark Main'
style={{width: '200px'}}
/>
</div>
</div>
:
unitTestsMode === 'Object' ?
<UnitTestsObjectView unitTestsData={unitTestsData}/>
: <UnitTestsDatabaseView unitTestsData={unitTestsData} />
}
{!targetObject ? null :
<div style={{position: 'fixed', bottom: '80px', right: '40px'}}>
<Button
text='New Test Case'
icon={<AddIcon className='ButtonIcon' />}
onClick={onNewTestCaseClick}
className='Button Dark Main'
/>
</div>
}
</PageWrapper>
)
}
export default withRouter(unitTests)

How to upload files using React?

so currently I am trying to upload a file, and save it on the Google Clouds. But I am stuck at how to get the input file using React-Redux.
Basically, my back-end part already finish, I tested it using HTTPie with this command
HTTP localhost:8000/v1/... #(file_path)
and it works perfectly fine.
Now after I use input tag:
<input type="file" onChange="">
I do not know how to get the file_path that are the user choose.
And I dont even know whether I can get the uploaded file using this method.
Thank you
You cant handle onChange file by method <input type="file" onChange={this.handleChangeFile.bind(this)}>
handleChangeFile(event) {
const file = event.target.files[0];
let formData = new FormData();
formData.append('file', file);
//Make a request to server and send formData
}
First : Create a component file name 'FileUpload.js'
import React, { Fragment, useState, useEffect } from 'react'
function FileUpload (props) {
useEffect(() => {
clearFileUpload()
}, [])
const [fileName, setFileName] = useState('')
const [fileSize, setFileSize] = useState('')
const [fileSizeKB, setFileSizeKB] = useState('')
const [fileType, setFileType] = useState('')
const [src, setSrc] = useState('')
const clearFileUpload = () => {
setFileName('')
setFileSize('')
setFileType('')
setSrc('')
props.dataChanger('')
}
const onPickFile = (e) => {
e.preventDefault();
clearFileUpload()
document.getElementById(props?.name).click()
}
const onFilePicked = (e) => {
let files = e.target.files;
let file_name = files[0].name;
let file_size = getFileSize(files[0].size);
let file_size_kb = getFileSizeKB(files[0].size);
let file_type = getFileType(files[0]).toLowerCase();
setFileName(file_name)
setFileSize(file_size)
setFileSizeKB(file_size_kb)
setFileType(file_type)
if (props?.max_file_size_in_kb && file_size_kb > props?.max_file_size_in_kb)
{
alert('Maximum allowed file size = '+props?.max_file_size_in_kb+ ' kb')
clearFileUpload()
return false;
}
if (props?.allowed_extensions && !arrToLowerCase(props?.allowed_extensions).includes(file_type))
{
clearFileUpload()
alert('Allowed file type = '+props?.allowed_extensions)
return false;
}
let fileReader = new FileReader();
fileReader.addEventListener('load', ()=>{
// console.log(fileReader.result);
props.dataChanger(fileReader.result)
setSrc(fileReader.result)
})
fileReader.readAsDataURL(files[0])
}
const getFileSize = (file_size) =>
{
if ( (file_size/1024) >= 1024 )
{
file_size= parseInt((file_size/1024)/1024) + ' MB';
}
else{
file_size=parseInt(file_size/1024) + ' KB';
}
return file_size;
}
const getFileSizeKB = (file_size) =>
{
file_size=parseInt(file_size/1024);
return file_size;
}
const getFileType = (file) =>
{
return file?.type.split('/').pop();
}
const arrToLowerCase = (arr=[]) => {
return arr.map(str => str.toLowerCase());
}
return (
<Fragment>
<button className="btn btn-primary text-capitalize mr-2 mb-2" onClick={(e) => onPickFile(e)}>{props?.button_title || 'Upload File'}</button>
{(props?.required && fileName?.length<=3 && !src ) ? <label className="label label-danger">Required</label> : ''}
<br />
{fileName ? <label className="label label-primary">{fileName}</label> : ''}
{fileSize ? <label className="label label-info">{fileSize}</label> : ''}
<br />
{/* new upload file */}
{(props?.type=='image' && src && (props?.prev_src)) ? <img src={src} style={{ maxHeight: "150px", maxWidth: "150px" }} alt="" className="mt-2" /> : ''}
{/* previous image */}
{(props?.type=='image' && (props?.prev_src) && !src) ? <img src={props?.prev_src} style={{ maxHeight: "150px", maxWidth: "150px" }} alt="" className="mt-2" /> : ''}
{(props?.type=='image' && src && (props?.prev_src)) ? <button className="btn btn-danger btn-outline-danger pl-1 pr-0 py-0 ml-2" onClick={clearFileUpload} title="Remove file"><i className="icofont icofont-ui-close"></i></button> : ''}
<input className='file d-none' type="file" data-show-upload="true" data-show-caption="true"
id={props?.name}
name={props?.name}
required={props?.required ? true : false}
onChange={(e) => onFilePicked(e)}
/>
</Fragment>
)
}
export default FileUpload
Second : How to use this component in your form
import FileUpload from './FileUpload.js'
<FileUpload
name="thumbImage"
button_title="Thumbnail Image Upload"
max_file_size_in_kb="200"
dataChanger={(value) => dataChangerThumbnail(value)}
type="image"
prev_src={'localhost:8001/'+formData?.thumbImage}
required
allowed_extensions={[ 'jpg', 'jpeg', 'png', 'gif']}
/>
const dataChangerThumbnail = (value) => {
setFormData({...formData, thumbImage: value})
}
const formInitial = {
thumbImage: '',
}
const [formData, setFormData] = useState(formInitial)
Checkout this blog, very well explained upload feature in react with example.
Below is upload code from above blog:
handleUploadedFiles = files => {
var reader = new FileReader();
reader.onload = (e) => {
//Split csv file data by new line so that we can skip first row which is header
let jsonData = reader.result.split('\n');
let data = [];
jsonData.forEach((element, index) => {
if(index) {
//Split csv file data by comma so that we will have column data
const elementRaw = element.split(',');
console.log(element, index);
if(element) {
let param = {
'id' : elementRaw[0],
'name' : elementRaw[1],
'age' : elementRaw[2],
'address' : elementRaw[3]
}
data.push(param);
}
}
});
}
console.log("TCL: Dashboard -> reader.readyState", reader.readyState)
reader.readAsText(files[0]);
}
Complete Example with AXIOS and FORMIK
import "./App.css";
import { useEffect, useState } from "react";
import * as Yup from "yup";
import { Formik, Field, Form, ErrorMessage, useField } from "formik";
import axios from "axios";
function App() {
return (
<Formik
initialValues={{
profile: [],
}}
validationSchema={Yup.object({
profile:Yup.array().min(1,"select at least 1 file")
})}
onSubmit={(values, props) => {
let data = new FormData();
values.profile.forEach((photo, index) => {
data.append(`photo${index}`, values.profile[index]);
});
axios
.post("you_api_for_file_upload", data, {
headers: {
"Content-Type": "multipart/form-data",
},
})
.then((response) => {
console.log(response);
})
.catch((err) => {
console.log(err);
});
}}
>
{(formik) => {
return (
<>
<Form>
<input
id="file"
name="profile"
type="file"
onChange={(event) => {
const files = event.target.files;
let myFiles =Array.from(files);
formik.setFieldValue("profile", myFiles);
}}
multiple
/>
<ErrorMessage name="profile"/>
<button type="submit" disabled={formik.isSubmitting}>
Submit
</button>
</Form>
</>
);
}}
</Formik>
);
}
export default App;
Hope this will help you

Resources