Reputation: 87
I'am using Formik for my forms in React. Everything is okay but for the file input.
The user must be able to upload a CV. The {values.cv} in Formik does indicate that there is a value in the input. However when I send it to my Laravel back-end, I get an empty array.
I want to be able to store the file in my database. Any help would be appreciated.
The Formik file input:
<label className="btn btn-info" htmlFor="cv">
<input id="cv" name="cv" style={{display: 'none'}} type="file" onChange={(event) => {
setFieldValue("cv", event.currentTarget.files[0]);
}} />
</label>
The cv input default value is : ' '
This is what is in the {values.cv} Here is the console.log of it
In my Laravel back-end I return the $request and React is logging it. This is what I see then.
cv : []
Here is a picture of my console
Upvotes: 3
Views: 7047
Reputation: 21925
As per this post.
<input id="file" name="file" type="file" onChange={(event) => {
setFieldValue("file", event.currentTarget.files[0]);
}} />
You can then access all the stuff...
JSON.stringify({
fileName: values.file.name,
type: values.file.type,
size: `${values.file.size} bytes`
}, null, 2);
Upvotes: 4
Reputation: 94
Formik doesn't handle file upload, but there's a hack around it provided here https://github.com/jaredpalmer/formik/issues/45
import * as React from 'react';
import { AxiosRequestConfig } from 'axios';
import Image from 'components/Image';
import { Progress } from 'components/Progress';
import ToasterInstance from '../Toast/ToasterInstance';
import { axios } from 'api/axios.config';
import { toApiError } from 'utils/api';
export interface MediaUploadProps {
id: string;
slug: string;
value: string;
onChange: (field: string, mediaId: string) => void;
}
export interface MediaUploadState {
progress: number;
file?: File;
error?: string;
}
export class MediaUpload extends React.Component<
MediaUploadProps,
MediaUploadState
> {
state: MediaUploadState = { progress: -1 };
handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
if (!e.target.files) {
return;
}
let file = e.target.files[0];
this.setState({ file: file });
let data = new FormData();
data.append('file', file);
let config: AxiosRequestConfig = {
onUploadProgress: (p: any) => {
this.setState({ progress: Math.round(p.loaded * 100 / p.total) });
},
};
this.setState({ error: undefined, progress: 0 });
axios.post('/v1/media?slug=' + this.props.slug, data, config).then(
res => {
this.setState({ error: undefined, progress: -1 });
this.props.onChange(this.props.id, res.data.path);
},
err => {
const message = toApiError(err);
this.setState({ error: message, progress: -1 });
ToasterInstance.show({
message,
iconName: 'danger',
intent: 'danger',
});
}
);
}
handleRemoveImage = () => {
this.props.onChange(this.props.id, '');
}
render() {
return (
<div>
<div>
{this.props.value !== '' &&
this.state.progress === -1 &&
<Image path={this.props.value} size="lg" />}
<div style={{ maxWidth: 144 }}>
{this.state.progress > -1 &&
<Progress percentage={this.state.progress} />}
</div>
{this.props.value &&
<a
style={{ marginTop: -40 }}
className="button button--negative button--small button--secondary"
role="button"
onClick={this.handleRemoveImage}
>
Remove
</a>}
</div>
<div style={{ marginTop: 10 }}>
<label className="button button--purple button--secondary">
Upload new picture
<input
className="visually-hidden"
type="file"
onChange={this.handleFileChange}
/>
</label>
</div>
</div>
);
}
}
Upvotes: 3