upload file with inertia react and laravel 9 - reactjs

im have problem with upload file with inertia react and laravel 9
i use this exact code but when i choose a file i got errors in console
https://inertiajs.com/file-uploads
Warning: A component is changing an uncontrolled input to be controlled. This is likely caused by the value changing from undefined to a defined value, which should not happen. Decide between using a controlled or uncontrolled input element for the lifetime of the component. More info: https://reactjs.org/link/controlled-components
input
form
Create#http://127.0.0.1:5173/resources/js/Pages/Admin/Setting/Content/ContactUs/Create.jsx?t=1659389601569:28:14
s#http://127.0.0.1:5173/node_modules/.vite/deps/#inertiajs_inertia-react.js?v=0d793d15:741:16
The above error occurred in the <input> component:
input
form
Create#http://127.0.0.1:5173/resources/js/Pages/Admin/Setting/Content/ContactUs/Create.jsx?t=1659389680993:28:14
s#http://127.0.0.1:5173/node_modules/.vite/deps/#inertiajs_inertia-react.js?v=0d793d15:741:16
Consider adding an error boundary to your tree to customize error handling behavior.
Visit https://reactjs.org/link/error-boundaries to learn more about error boundaries.
this is my code
import React from "react";
import Button from "#mui/material/Button";
import { Link, useForm, usePage } from "#inertiajs/inertia-react";
export default function Create() {
const { data, setData, post, progress } = useForm({
name: null,
avatar: null,
});
function submit(e) {
e.preventDefault();
post("/users");
}
return (
<form onSubmit={submit}>
<input
type="text"
value={data.name}
onChange={(e) => setData("name", e.target.value)}
/>
<input
type="file"
value={data.avatar}
onChange={(e) => setData("avatar", e.target.files[0])}
/>
{progress && (
<progress value={progress.percentage} max="100">
{progress.percentage}%
</progress>
)}
<button type="submit">Submit</button>
</form>
);
}
i think its problem with onChange={(e) => setData("avatar", e.target.files[0])}

I had the same issue... I solved removing the value attribute from the input type="file".
<input
type="file"
onChange={(e) => setData("avatar", e.target.files[0])}
/>
(If you see in the documentation the same example for svelte or vue, you will not see the value attribute there).

Related

Formik issue: Unable to edit text field in simple form in React app

I am unable to enter any text into a text input field within a plain html form that uses formik to handle changes to the field and to handle submit.
See the issue in action here:
https://formik-plain-form-issue.netlify.app/
I have encountered this issue while working on an app that uses Formik in combination with Redux, Bootstrap and Reactstrap, so I thought the issue may be related to these other libraries. However, a simplified version with a plain form and no state management is also showing a similar behaviour.
Here I am providing the code for the simplified version.
PlainForm component code:
// This is a React component
import { useFormik } from 'formik';
import './PlainForm.css';
const PlainForm = () => {
const formik = useFormik({
initialValues: {
name: '',
},
onSubmit: values => {
alert(`Plain form submitted with name: ${values.name}`);
},
});
return (
<div className='plain-form-container'>
<h1>Plain Form</h1>
<form
className='baseForm'
onSubmit={formik.handleSubmit}
noValidate
>
<label htmlFor='plain-form-name'>Name:</label>
<input
type='text'
id='plain-form-name'
className='nameField'
placeholder='Enter your name here'
value={formik.values.name}
onChange={formik.handleChange}
/>
<button type='submit'>Submit</button>
</form>
</div>
);
};
export default PlainForm;
You may see the full code for the test app here:
https://github.com/freenrg/Formik-Plain-Form-Issue
As pointed out by #shadow-lad in the comments, Formik needs the form field to have id and name matching the key of the property defined for that field in initialValues.
See https://formik.org/docs/tutorial
If you look carefully at our new code, you’ll notice some patterns and symmetry forming.
We reuse the same exact change handler function handleChange for each
HTML input
We pass an id and name HTML attribute that matches the property we defined in initialValues
We access the field’s value
using the same name (email -> formik.values.email)
Therefore, the code should be:
// This is a React component
import { useFormik } from 'formik';
import './PlainForm.css';
const PlainForm = () => {
const formik = useFormik({
initialValues: {
name: '',
},
onSubmit: values => {
alert(`Plain form submitted with name: ${values.name}`);
},
});
return (
<div className='plain-form-container'>
<h1>Plain Form</h1>
<form
className='baseForm'
onSubmit={formik.handleSubmit}
noValidate
>
<label htmlFor='plain-form-name'>Name:</label>
<input
type='text'
id='name'
name='name'
className='nameField'
placeholder='Enter your name here'
value={formik.values.name}
onChange={formik.handleChange}
/>
<button type='submit'>Submit</button>
</form>
</div>
);
};
export default PlainForm;
I have confirmed this works.

Trouble uploading image with InertiaJS, React and Laravel

The job is very simple: Take postTitle, postBody and postImage as input and update them in database. But I am facing difficulties uploading the image, hope someone will help me. I am using InertiaJs, React and Laravel.
My EditPost.jsx file:
import {React, useState, useEffect} from 'react'
import Layout from '../Shared/Layout'
import { useForm } from '#inertiajs/inertia-react'
function EditPost({errors, postId, postTitle, postBody, postImage}) {
const { data, setData, put, progress } = useForm({
postTitle: postTitle,
postBody: postBody,
postImage: null
})
const onSubmitHandler = (e) => {
e.preventDefault()
put('/posts/update/' + postId)
}
return (
<div className="container">
<div className="row justify-content-center">
<div className="col-md-8">
<br/>
<br/>
<h3 className="text-center">Edit the post</h3>
<form onSubmit={onSubmitHandler}>
<div className="mb-3">
<label htmlFor="postTitle" className="form-label">Post title</label>
<input value={data.postTitle} onChange={e => setData('postTitle', e.target.value)} type="text" className="form-control" id="postTitle" placeholder="Enter post title here..." />
{errors.postTitle && <p className="text-danger">{errors.postTitle}</p>}
</div>
<div className="mb-3">
<label htmlFor="postBody" className="form-label">Post body</label>
<input value={data.postBody} onChange={e => setData('postBody', e.target.value)} type="text" className="form-control" id="postBody" placeholder="Enter post body here..." />
{errors.postBody && <p className="text-danger">{errors.postBody}</p>}
</div>
<div className="mb-3">
<label htmlFor="postImage" className="form-label">Post body</label>
<input type="file" className="form-control" id="postImage" value={data.postImage} onChange={e => setData('postImage', e.target.files[0])} />
{errors.postImage && <p className="text-danger">{errors.postImage}</p>}
</div>
{progress && (
<progress value={progress.percentage} max="100">{progress.percentage}%
</progress>
)}
<br/>
<button className="btn btn-success rounded">Submit</button>
</form>
</div>
</div>
</div>
)
}
EditPost.layout = page => <Layout pageTitle={'Edit the Post'} children={page}/>
export default EditPost
I am following the InertiaJS documentation but getting this warning in console:
Warning: `value` prop on `input` should not be null. Consider using an empty string to clear the component or `undefined` for uncontrolled components.
[.......]
If I ignore the error and select file, I get the following errors:
Uncaught DOMException: Failed to set the 'value' property on 'HTMLInputElement': This input element accepts a filename, which may only be programmatically set to the empty string.
react_devtools_backend.js:2556 Warning: A component is changing an uncontrolled input of type file to be controlled. Input elements should not switch from uncontrolled to controlled (or vice versa). Decide between using a controlled or uncontrolled input element for the lifetime of the component.
Uncaught DOMException: Failed to set the 'value' property on 'HTMLInputElement': This input element accepts a filename, which may only be programmatically set to the empty string.
Please help me out...
Try using POST instead of PUT, otherwise you would need to spoof the method.
Also if the version of Inertia you are using is below 0.8.0, you will need to pass the information as a FormData object.
Uploading files using a multipart/form-data request is not natively supported in some languages for the put, patch or delete methods. The workaround here is to simply upload files using post instead.
Check out the page on Inertia file uploads here which has a React example.

In this basic react application, why does the custom component `TextInput` allow me to type stuff in even though the regular `input` field doesn't?

I have a basic react form that I am testing out currently. It's still incomplete, but I have discovered unexpected behaviour.
The regular input field doesn't allow me to type in anything, as I am not updating the state yet. However, my custom TextInput component does allow me to type stuff in... Surprising, as I said before, I am not using setValues to update the state yet.
import React, { useState } from 'react';
const App = () => {
const [values, setValues] = useState({
firstName: '',
lastName: ''
});
return (
<div>
<form>
{/* [EXPECTED] this doesn't allow anything to be typed in at the front-end... which is expected...
... as I am not using `setValues` to update the state yet */}
<input
type="text"
id="first-name"
name="firstName"
value={values.firstName}
/>
{/* [NOT EXPECTED] this does allow stuff to be typed in at the front-end... which is strange...
... as I am not using `setValues` to update the state yet */}
<TextInput
id="last-name"
name="lastName"
value={values.lastName}
/>
<button type="submit">
Register
</button>
</form>
</div>
);
};
const TextInput = props => {
return (
<input
type="text"
id={props.id}
name={props.name}
/>
/* <span id={props.id + '-error'}>{props.title}</span> */
);
};
export default App;
Can anybody help me to explain why the difference?
Your first input is controlled - it has a value prop which is used to determine what the value of the element should be when rendered:
<input
type="text"
id="first-name"
name="firstName"
value={values.firstName}
/>
No matter what you type into it, since it's "controlled", the value that exists in it will always be what's currently in state as values.firstName.
In contrast, your second input is uncontrolled. It has no value prop:
<input
type="text"
id={props.id}
name={props.name}
/>
So, since you're not giving React any directives on what its value should be while being rendered, you can type whatever you want into it, and it won't be in conflict with React state.

Creating a controlled form with Grommet throws errors

I am trying to create a basic form using Grommet following the examples at https://v2.grommet.io/form. My specific form looks like this:
import React from 'react';
import { Box, Form, FormField, TextInput, Button } from 'grommet';
const defaultValue = {};
const LoginForm = () => {
const [value, setValue] = React.useState(defaultValue);
function handleSubmit(e) {
e.preventDefault();
const { email, password } = e.value;
console.log('pretending to log in:', email, password);
// doLogin(email, password)
}
return (
<Form
value={value}
onChange={nextValue => {
setValue(nextValue);
}}
onReset={() => setValue(defaultValue)}
onSubmit={handleSubmit}
>
<FormField label="email" name="email" required>
<TextInput name="email" />
</FormField>
<FormField label="password" name="password" required>
<TextInput name="password" />
</FormField>
<Box direction="row" justify="between" margin={{ top: 'medium' }}>
<Button type="reset" label="Reset" />
<Button type="submit" label="Login" primary />
</Box>
</Form>
);
};
As soon as I start typing into either field, I get the following:
Warning: A component is changing an uncontrolled input of type undefined to be controlled. Input elements should not switch from uncontrolled to controlled (or vice versa). Decide between using a controlled or uncontrolled input element for the lifetime of the component. More info: ...
Note that I get the exact same error if I replace my form code with a cut/paste from the example in the link above.
I have a fairly reasonable understanding of what the error means, but I have no idea how to fix it in this case. Is Grommet's implementation of controlled form components broken, or am I missing something elsewhere in my configuration or packages that might be causing this?
The React.js controlled standards are not allowing objects to be undefined.
So the problem starts with how you've defined your defaultValue = {};, since it is an empty object, there is no initial value to the FormField children and that causes them to be undefined and hence the error.
So if you'll change the preset value to be more accommodating to your fields, such as defaultValue = { password: '' }; it will fix your error.
For more reading about React controlled and uncontrolled inputs read this A component is changing an uncontrolled input of type text to be controlled error in ReactJS

Redux Form wrapper for kendo-react-ui Input error

I am using react-kendo-ui. I want to wrap Input from #progress/kendo-react-inputs to use it with ReduxForm. Please find my code below:
import React from 'react'
import { Input } from '#progress/kendo-react-inputs';
const InputText = ({ input, label, type, meta: { touched, error } }) => (
<div>
<label>{label}</label>
<div>
<Input {...input} type={type} placeholder={label} />
{touched && error && <span>{error}</span>}
</div>
</div>
)
export default InputText
Call the InputText from another component as below:
import React from 'react';
import { Field, reduxForm } from 'redux-form';
import { Input } from '#progress/kendo-react-inputs';
import InputText from './input-text';
const validateNotEmpty = value => !value ? 'Must enter a value' : null;
const onSubmit = (values) => {
console.log(values);
}
const AddLoc= ({ handleSubmit }) => (
<form onSubmit={handleSubmit}>
<div>
<Field
label="Address"
name="address"
component={InputText}
validate={validateNotEmpty}
/>
</div>
<button type="submit">Submit</button>
</form>
)
export default reduxForm({
form: 'AddLoc'
})(AddLoc)
But while typing inside the input text it keeps giving the following error/warning:
Warning: This synthetic event is reused for performance reasons. If you're seeing this, you're accessing the property `nativeEvent` on a released/nullified synthetic event. This is set to null. If you must keep the original synthetic event around, use event.persist().
While typing inside the input text automatically outputs [object Object]. Please check the image above. Could anyone please let me know what is causing the error.
Thanks
The reduxForm works only with pure DOM <input />. Internally it clones the elements search the children and then attaches the onChange dynamically. So it will not work with the Input and the NumericTextBox from the #progress/kendo-react-inputs package. This statement is based on the official kendo documentation about integrating with the redux-form.
The same author of the redux-form have fork of it called react-final-form which could be used on any component that have Value and onChange props. By our tests it works with the components from #progress/kendo-react-inputs and #progress/kendo-react-dropdowns packages. It looks kendo already have an example using final-form in their integration section.

Resources