Create dynamic json based on user input - reactjs

I have two dropdowns and a couple of images on it what I want is when the user selects the dropdowns and selects image I want to create the JSON format like below:
[data: {
dropdown1:'user input',
dropdown2:'user input',
image url:'url'
}]
my react code:
import React from "react";
import axios from 'axios'
import '../Login.css'
export default class Inference extends React.Component {
constructor(props) {
super(props);
this.state = {
courses: [],
course: "",
inferenceout: [],
model: "",
isLoading: false,
options: [
{ label: "resnet-50torch", value: "resnet-50torch" },
{ label: "densenet_onnx", value: "densenet_onnx" },
{ label: "inception_graphdef", value: "inception_graphdef" },
],
};
this.handleChange = this.handleChange.bind(this);
this.handleChangeCourse = this.handleChangeCourse.bind(this);
this.click = this.click.bind(this);
}
handleChange(e) {
console.log("Model Selected!!");
this.setState({ model: e.target.value });
}
handleChangeCourse = (event) => {
this.setState({ course: event.target.value });
};
getUnique(arr, comp) {
const unique = arr
//store the comparison values in array
.map((e) => e[comp])
// store the keys of the unique objects
.map((e, i, final) => final.indexOf(e) === i && i)
// eliminate the dead keys & store unique objects
.filter((e) => arr[e])
.map((e) => arr[e]);
return unique;
}
click() {
this.setState({ isLoading: true });
axios
.get(
`http://localhost:5000/model-list`
)
.then((res) => {
this.setState({
inferenceout: res.data , isLoading: false,
})
let newWin = window.open("about:blank", "res.data", "width=400,height=400");
newWin.document.write(JSON.stringify(res.data))
localStorage.setItem("apiData", JSON.stringify(res.data));
var data = JSON.parse(localStorage.getItem("apiData"));
console.log(data)
})
}
handleSubmit(event) {
event.preventDefault();
axios.post('http://localhost:5000/getmodel', {
model: this.state.model,
dataset:this.state.course
})
.then((res) => {
// Res.data is the response from your server
localStorage.setItem("apiData1", JSON.stringify(res.data));
});
var data = JSON.parse(localStorage.getItem("apiData1"));
console.log(data)
}
componentDidMount() {
axios
.get(`http://localhost:5000/files`)
.then((response) =>
this.setState(
{
courses: response.data
},
)
)
.catch((err) => console.log(err))
}
render() {
const uniqueCouse = this.getUnique(this.state.courses, "dataset");
const { courses, course, options } = this.state;
const filterDropdown = courses.filter(function (result) {
return result.dataset === course;
});
return (
<div className="container">
<div className="row">
<div
className="col-6"
style={{
paddingBottom: "100px",
paddingTop: "20px",
alignItems: "center",
}}
>
<label
className=""
style={{ paddingTop: "5px", marginTop: "40px" }}
>
Dataset
<form onSubmit={this.handleSubmit.bind(this)}>
<select
className="custom-select"
value={this.state.course}
onChange={this.handleChangeCourse}
style={{ paddingTop: "5px", marginTop: "10px" }}
>
<option>--Select--</option>
{uniqueCouse.map((course) => (
<option key={course.id} value={course.dataset}
onChange={(e) => this.setState({ dataset: e.target.value })}>
{course.dataset}
</option>
))}
</select>
<button
type="submit"
class="btn"
style={{ marginTop: "" }}
>
ok
</button>
</form>
</label>
</div>
<div
className="col-6"
style={{
paddingBottom: "100px",
paddingTop: "20px",
alignItems: "center",
}}
>
<label
className=""
style={{ paddingTop: "5px", marginTop: "40px" }}
>
Model
<form onSubmit={this.handleSubmit.bind(this)}>
<select
className="custom-select"
name="example"
value={this.state.model}
onChange={this.handleChange}
style={{ paddingTop: "5px", marginTop: "10px" }}
>
<option>--Select--</option>
{options.map((option) => (
<option
value={option.value}
onChange={(e) => this.setState({ model: e.target.value })}
>
{option.label}
</option>
))}
</select>
<button
type="submit"
class="btn"
style={{ marginTop: "" }}
>
ok
</button>
</form>
</label>
</div>
{filterDropdown.map((course) => (
<div className="col-2">
<input type="checkbox" id="myCheckbox1" />
<label for="myCheckbox1" className="labell">
<img
key={course.id}
src={`${course.path}`}
height="80"
className="card-img-top img-responsive"
alt="img"
/>
</label>
</div>
))}
<button
type="submit" onClick={this.click} disabled={this.state.isLoading}
class="btn btn-success"
style={{ marginLeft:"45%" ,marginBottom:"10px"}}
>
Inference
</button>
<button
type="submit"
class="btn btn-primary"
style={{ marginLeft:"45%"}} onClick={()=> window.open("/visual", "data","width=400,height=400")}
>
Get Output
</button>
</div>
</div>
);
}
}
the dropdown data are coming from nodejs and images from nodejs also. i want to get the user input as a JSON. i couldn't able to do that thats why i'm asking here kindly help me
please guide me on how to do that

Related

How can I add the 'All' checkbox in order to select all the other options?

how can I add the All checkboxes that will select all the other checkboxes for each Type of plant and adding a checkbox in front of each Type of plant section. So when I select one option Plant 1.1 then my checkbox for Type of plant #1 is filled, and if option is filled then the checkbox for Type of plant is not filled.
export default function Category({
_id_type,
name_type,
plants,
changeSelection
}) {
const [toggleState, setToggleState] = useState(false);
return (
<div key={_id_type}>
<div
style={{
cursor: "pointer",
userSelect: "none",
display: "flex",
margin: "2px",
backgroundColor: "lightgray"
}}
onClick={() => setToggleState((prev) => !prev)}
>
<div>{name_type}</div>
<div
style={{
backgroundColor: "blue",
color: "white",
padding: "0px 10px",
marginLeft: "auto"
}}
>
{plants.filter(({ selected }) => selected).length}
</div>
</div>
<div style={{ marginLeft: "10px" }}>
{toggleState &&
plants.map(({ name, _id, selected }) => (
<div key={_id}>
<input
key={_id}
type="checkbox"
value={name}
checked={selected}
onChange={(e) => changeSelection(_id_type, _id, e.target.value)}
/>
{name}
</div>
))}
</div>
</div>
);
}
Here a picture (what I have/ what I want) :
Here is my code
add new toogle inside category.jsx
{toggleState && plants.length > 1 ? (
<div>
<input
type="checkbox"
value={"all"}
checked={allSelected}
onChange={(e) => {
setAllSelected((v) => {
changeSelection(_id_type, "all", e.target.value, !v);
return !v;
});
}}
/>
All
</div>
) : (
""
)}
edit change selection function:
const changeSelection = (catId, itemId, value, allSelected) => {
setSelectionMenu((prevSelectionMenu) =>
prevSelectionMenu.map((item) => {
if (item._id_type === catId) {
return {
...item,
plants: item.plants.map((plant) => {
if (plant._id === itemId) {
return { ...plant, selected: !plant.selected };
} else if (itemId === "all") {
return { ...plant, selected: allSelected };
}
return plant;
})
};
}
return item;
})
);
};
here the forked code:
https://codesandbox.io/embed/plants-forked-qdmz2h?fontsize=14&hidenavigation=1&theme=dark

Using working fileupload code inside a form with formki api

I have my form using formik. and I want to use the file upload logic in my form which is shown in the sandbox here.
Quick Description of what's in sandbox:
User uploads a file, and based on the # of files, they will see a datatable rows and answer some questions by editing that row using edit button and then saving their response using checkmark button.
Right now, when a user hits Save button, it prints in the console log the values of what user has selected as an array of object.
I don't want to have this additional Save button in my form and want to send these values when a user hits the Submit button of my form along with other values.
I was playing with my sandbox code by putting it at the location in my form where {uploadDocumentSection} is mentioned in my code below. However,
I'm unable to get the data from the dynamicData variable which is storing the responses from the user.
Is it possible to achieve what I'm looking for?
return (
<div>
<style jsx>{`
text-align: center;
padding: 5px;
#formEdwDiv {
padding: 20px;
}
`}
</style>
<div id="formEdwDiv">
<Growl ref={growl}/>
<Form className="form-column-3">
<div className="datarequest-form">
<div className="form-field field-full-width">
<label className="MuiFormLabel-root MuiInputLabel-root MuiInputLabel-animated custom-label">Title <span className="astrick">*</span></label>
<CustomTextField name="title" type="text"/>
</div>
<div className="form-field field-full-width">
<label className="MuiFormLabel-root MuiInputLabel-root MuiInputLabel-animated custom-label">Description <span className="astrick">*</span></label>
<CustomTextAreaField name = "description" type ="text" />
{touched.description && errors.description && <Message severity="error" text={errors.description}/>}
</div>
</div>
{uploadDocumentSection}
<div className="btn-group-right">
<Button size="large" variant="contained" color="primary" id="edw-submit"
type="submit">Submit</Button>
<Button size="large" variant="contained" color="primary" onClick={handleReset}
style={{marginLeft: '5px'}} type="button">Reset</Button>
<Button size="large" variant="contained" color="primary" onClick={props.onCancel}
style={{marginLeft: '5px'}} type="button">Cancel</Button>
</div>
</Form>
</div>
</div>
)
};
export const RequestEnhancedForm = withFormik(
{
mapPropsToValues: props => {
return {
requestId: props.dataRequest && props.dataRequest.requestId || '',
title: props.dataRequest && props.dataRequest.title || '',
}
},
validationSchema:validationSchema,
handleSubmit(values, {props, resetForm, setErrors, setSubmitting}) {
console.log("submit data request form....")
props.handleSubmit(values)
setSubmitting(false)
},
setFieldValue(field, value, shouldVal) {
console.log('In setFieldValue')
},
displayName: 'Data Request Form',
})(DataRequestForm)
Here is my code from Codesandbox if needed:
const answers = [
{ label: "Yes", value: "YES" },
{ label: "No", value: "NO" }
];
export const FileUploadDemo = () => {
const toast = useRef(null);
const fileUploadRef = useRef(null);
const [dynamicData, setDynamicData] = useState([]);
const getAnswerLabel = (answer) => {
switch (answer) {
case "YES":
return "Yes";
case "NO":
return "No";
default:
return "NA";
}
};
const onRowEditComplete1 = (e) => {
console.log("Testing e");
console.log(e);
let _dynamicData = [...dynamicData];
let { newData, index } = e;
_dynamicData[index] = newData;
setDynamicData(_dynamicData);
};
const textEditor = (options) => {
return (
<InputText
type="text"
value={options.value}
onChange={(e) => options.editorCallback(e.target.value)}
/>
);
};
const answerEditor = (options) => {
return (
<Dropdown
value={options.value}
options={answers}
optionLabel="label"
optionValue="value"
onChange={(e) => options.editorCallback(e.value)}
placeholder="Select an answer"
itemTemplate={(option) => {
return <span className={`product-badge`}>{option.label}</span>;
}}
/>
);
};
const answer1BodyTemplate = (rowData) => {
return getAnswerLabel(rowData.answer1);
};
const answer2BodyTemplate = (rowData) => {
return getAnswerLabel(rowData.answer2);
};
const onUpload = (e) => {
// toast.current.show({
// severity: "info",
// summary: "Success",
// detail: "File Uploaded"
// });
console.log("File Upload event e");
console.log(e);
const newData = e.files.map((file) => ({
filename: file.name,
answer1: null,
answer2: null,
description: ""
}));
setDynamicData([...dynamicData, ...newData]);
};
return (
<div>
<Tooltip target=".custom-choose-btn" content="Choose" position="bottom" />
<Tooltip target=".custom-upload-btn" content="Upload" position="bottom" />
<Tooltip target=".custom-cancel-btn" content="Clear" position="bottom" />
<div className="card">
<h5>Advanced</h5>
<FileUpload
name="demo[]"
url="https://primefaces.org/primereact/showcase/upload.php"
onUpload={onUpload}
customUpload
uploadHandler={onUpload}
multiple
accept="image/*"
maxFileSize={1000000}
emptyTemplate={
<p className="m-0">Drag and drop files to here to upload.</p>
}
/>
</div>
<div className="datatable-editing-demo">
{/* <Toast ref={toast} /> */}
<div className="card p-fluid">
<h5>Row Editing</h5>
<DataTable
value={dynamicData}
editMode="row"
dataKey="id"
onRowEditComplete={onRowEditComplete1}
responsiveLayout="scroll"
>
<Column
field="filename"
header="Filename"
editor={(options) => textEditor(options)}
style={{ width: "20%" }}
></Column>
<Column
field="answer1"
header="Q1"
body={answer1BodyTemplate}
editor={(options) => answerEditor(options)}
style={{ width: "20%" }}
></Column>
<Column
field="answer2"
header="Q2"
body={answer2BodyTemplate}
editor={(options) => answerEditor(options)}
style={{ width: "20%" }}
></Column>
<Column
field="description"
header="Description"
editor={(options) => textEditor(options)}
style={{ width: "20%" }}
></Column>
<Column
rowEditor
headerStyle={{ width: "10%", minWidth: "8rem" }}
bodyStyle={{ textAlign: "center" }}
></Column>
</DataTable>
</div>
</div>
<Button label="Save" onClick={() => console.log(dynamicData)} />
</div>
);
};
const rootElement = document.getElementById("root");
ReactDOM.render(<FileUploadDemo />, rootElement);

Validation of textbox message:- (fill the value)

I dont know how to validate the textbox in this so can anyone do for one textbox other all box i will do on myself i watch videos but i am not geatting it.....
I dont know how to validate the textbox in this so can anyone do for one textbox other all box i will do on myself i watch videos but i am not geatting it.....
I dont know how to validate the textbox in this so can anyone do for one textbox other all box i will do on myself i watch videos but i am not geatting it.....
I dont know how to validate the textbox in this so can anyone do for one textbox other all box i will do on myself i watch videos but i am not geatting it.....
import React, { useState } from 'react'
import './AddRecipes.css'
import axios from 'axios'
function AddRecipes() {
const [state, setstate] = useState({
label: '',
source: '',
dietlabels: [],
healthlabels: [],
cuisineType: [],
ingredients: [],
mealType: [],
makingDescription: '',
recipeImage: null
})
state={
dietlabels= " This is empty fild",
healthlabels= "",
cuisineType ="",
ingredients= "",
mealType= ""
};
const onFormSubmit = async (e) => {
e.preventDefault()
console.log(state.ingredients)
try {
const fd = new FormData()
fd.append('recipeImage', state.recipeImage, state.recipeImage.name)
fd.append('label', state.label)
fd.append('source', state.source)
fd.append('dietlabels', JSON.stringify(state.dietlabels))
fd.append('healthlabels', JSON.stringify(state.healthlabels))
fd.append('ingredients', JSON.stringify(state.ingredients))
fd.append('cuisineType', JSON.stringify(state.cuisineType))
fd.append('mealType', JSON.stringify(state.mealType))
fd.append('makingDescription', state.makingDescription)
// console.log(fd)
const { data: response } = await axios.post(
'http://localhost:8000/recipe',
fd
)
console.log('api response' + response)
} catch (error) {
console.log(error)
}
}
const [arrayState, arraySetSate] = useState({
dietlabels: '',
healthlabels: '',
cuisineType: '',
ingredients: { text: '', weight: '' },
mealType: ''
})
const subIngredientStatePush = (event) => {
let replica = { ...arrayState }
replica.ingredients[event.target.name] = event.target.value
arraySetSate(replica)
}
//string type field data handling
const stringTypeFieldDataHandler = (event) => {
let replicateState = { ...state }
replicateState[event.target.name] = event.target.value
setstate(replicateState)
}
//image file handling
const imageUploadFileHandler = (event) => {
let replicateState = { ...state }
replicateState['recipeImage'] = event.target.files[0]
setstate(replicateState)
}
//array elements data handling
const arrayElementSeparateStateHandler = (event) => {
let repilica = { ...arrayState }
repilica[event.target.name] = event.target.value
arraySetSate(repilica)
}
const addDietLabels = () => {
let replica = { ...state }
let arrayreplica = { ...arrayState }
replica.dietlabels.push(arrayState.dietlabels)
setstate(replica)
arrayreplica.dietlabels = ''
arraySetSate(arrayreplica)
}
const newlable =()=>{
}
const addHealthLables = () => {
let replica = { ...state }
let arrayreplica = { ...arrayState }
replica.healthlabels.push(arrayState.healthlabels)
setstate(replica)
arrayreplica.healthlabels = ''
arraySetSate(arrayreplica)
}
const addcuisineType = () => {
let replica = { ...state }
let arrayreplica = { ...arrayState }
replica.cuisineType.push(arrayState.cuisineType)
setstate(replica)
arrayreplica.cuisineType = ''
arraySetSate(arrayreplica)
}
const addmealType = () => {
let replica = { ...state }
let arrayreplica = { ...arrayState }
replica.mealType.push(arrayState.mealType)
setstate(replica)
arrayreplica.mealType = ''
arraySetSate(arrayreplica)
}
const AddingredientsClick = () => {
let replica = { ...state }
let arrayreplica = { ...arrayState }
let ingredientObj = {
text: arrayState.ingredients.text,
weight: arrayState.ingredients.weight
}
replica.ingredients.push(ingredientObj)
setstate(replica)
arrayreplica.ingredients = { text: '', weight: '' }
arraySetSate(arrayreplica)
}
return (
<div className="recipeForm container">
<form
style={{
display: 'flex',
flexDirection: 'column',
width: '70%',
alignItems: 'center'
}}
>
<label className="addrecipe-labels" htmlFor="label">
Enter Recipe Name
</label>
<input
type="text"
id="label"
name="label"
placeholder="recipe name"
className="inputs"
value={state.label}
onChange={stringTypeFieldDataHandler}
/>
<br />
<label className="addrecipe-labels" htmlFor="source">
Recipe Source
</label>
<input
type="text"
id="source"
name="source"
placeholder="enter source"
value={state.source}
onChange={stringTypeFieldDataHandler}
className="inputs"
/>
{/* <label className="addrecipe-labels" htmlFor="url">
URL
</label>
<input
type="text"
id="url"
name="url"
placeholder="paste url"
className="inputs"
/> */}
<div
style={{
display: 'flex',
flexDirection: 'row',
justifyContent: 'space-evenly',
margin: '5px 5px'
}}
>
<label className="addrecipe-labels" htmlFor="dietlabels">
diet labels
</label>
<input
type="text"
id="dietlabels"
name="dietlabels"
onChange={arrayElementSeparateStateHandler}
onChange={newlable}
value={arrayState.dietlabels}
placeholder="type labels"
className="inputs"
/>
<div>{this.state.nameError}</div>
<button
style={{ width: '40px' }}
type="button"
onClick={addDietLabels}
>
Add
</button>
<p>{String(state.dietlabels)}</p>
</div>
<div
style={{
display: 'flex',
flexDirection: 'row',
justifyContent: 'space-evenly',
margin: '5px 5px'
}}
>
<label className="addrecipe-labels" htmlFor="healthlabels">
Health labels
</label>
<input
type="text"
value={arrayState.healthlabels}
onChange={arrayElementSeparateStateHandler}
id="healthlabels"
name="healthlabels"
placeholder="health lables"
className="inputs"
/>
<button
style={{ width: '40px' }}
type="button"
onClick={addHealthLables}
>
Add
</button>
{String(state.healthlabels)}
</div>
<div
style={{
display: 'flex',
flexDirection: 'row',
justifyContent: 'space-evenly',
margin: '5px 5px'
}}
>
<label className="addrecipe-labels" htmlFor="cuisineType">
cuisine type
</label>
<input
type="text"
id="cuisineType"
value={arrayState.cuisineType}
onChange={arrayElementSeparateStateHandler}
name="cuisineType"
placeholder="add cautions"
className="inputs"
/>
<button
style={{ width: '40px' }}
type="button"
onClick={addcuisineType}
>
Add
</button>
{String(state.cuisineType)}
</div>
<div
style={{
display: 'flex',
flexDirection: 'row',
justifyContent: 'space-evenly',
margin: '5px 5px'
}}
>
<label className="addrecipe-labels" htmlFor="mealtype">
meal type
</label>
<input
type="text"
id="mealtype"
name="mealType"
value={arrayState.mealType}
onChange={arrayElementSeparateStateHandler}
placeholder="add cautions"
className="inputs"
/>
<button style={{ width: '40px' }} type="button" onClick={addmealType}>
Add
</button>
{String(state.mealType)}
</div>
<div
style={{
display: 'flex',
flexDirection: 'row',
justifyContent: 'space-evenly',
margin: '5px 5px'
}}
>
<label className="addrecipe-labels" htmlFor="ingredients">
ingredients
</label>
<input
type="text"
id="ingredients"
name="text"
value={arrayState.ingredients.text}
placeholder="ingredient"
className="inputs"
onChange={subIngredientStatePush}
style={{ margin: '0 5px' }}
/>
<input
type="text"
id="quantity"
name="weight"
value={arrayState.ingredients.weight}
onChange={subIngredientStatePush}
placeholder="quantity"
className="inputs"
/>
<button
style={{ width: '50px', marginLeft: '7px' }}
type="button"
onClick={AddingredientsClick}
>
Add
</button>
{JSON.stringify(state.ingredients)}
</div>
{/*
<label className="addrecipe-labels" htmlFor="country">
Country
</label>
<select id="country" name="country" className="inputs">
<option value="australia">Australia</option>
<option value="canada">Canada</option>
<option value="usa">USA</option>
</select> */}
<label className="addrecipe-labels" htmlFor="recipe-description">
Recipe description
</label>
<textarea
id="recipe-description"
name="makingDescription"
value={state.makingDescription}
onChange={stringTypeFieldDataHandler}
placeholder="Write something.."
style={{ height: '200px' }}
className="inputs"
></textarea>
<div style={{ margin: '15px 0' }}>
<label className="addrecipe-labels" htmlFor="recipeImage">
Add recipe image
</label>
<input
type="file"
name="recipeImage"
onChange={imageUploadFileHandler}
id="recipeImage"
/>
</div>
<input
type="submit"
value="Submit"
className="inputs submit"
onClick={onFormSubmit}
/>
</form>
</div>
)
}
export default AddRecipes
You have a couple of mistakes within your code but I'll focus on your question.
To validate, you add the validation logic either to the onChange or onSubmit callback.
onChange callback example
const subIngredientStatePush = ({ target: { name, value }}) => {
// validate
if (name === "text" && value.length > 10) {
setError((errors) => ({ ...errors, [name]: "too long" });
}
//... etc
// update state
const replica = { ...arrayState };
replica.ingredients = { ...replica.ingredients }; // need to copy this state as well
replica.ingredients[name] = value
arraySetSate(replica)
}

Fetch axios response to new window or new url

i'm created one dropdown that used for querying the database and show the result as axios response . but right now i can only use it in console.log(res.data) what i want is something like load response in new url or new file.
full react code:
import React from "react";
import axios from 'axios';
class Inference extends React.Component {
constructor(props) {
super(props);
this.state = {
courses: [],
course: "",
model: "",
options: [
{ label: "model1", value: "model1" },
{ label: "model2", value: "model2" },
{ label: "model3", value: "model3" },
],
};
this.handleChangeCourse = this.handleChangeCourse.bind(this);
this.handleChange = this.handleChange.bind(this);
}
handleChange = event => {
this.setState({ model: event.target.value });
};
handleChangeCourse = event => {
this.setState({ course: event.target.value });
};
getUnique(arr, comp) {
const unique = arr
//store the comparison values in array
.map(e => e[comp])
// store the keys of the unique objects
.map((e, i, final) => final.indexOf(e) === i && i)
// eliminate the dead keys & store unique objects
.filter(e => arr[e])
.map(e => arr[e]);
return unique;
}
handleSubmit(event) {
event.preventDefault();
axios.post('http://localhost:5000/getmodell', {
model: this.state.model,
dataset:this.state.course
})
.then((res) => {
// Res.data is the response from your server
console.log(res.data);
});
}
componentDidMount() {
axios.get('http://localhost:5000/files')
.then(response => this.setState({ courses: response.data }));
}
render() {
const uniqueCouse = this.getUnique(this.state.courses, "dataset");
const courses = this.state.courses;
const course = this.state.course;
const options = this.state.options;
const filterDropdown = courses.filter(function(result) {
return result.dataset === course;
});
return (
<div className="container">
<div className="row">
<form onSubmit={this.handleSubmit.bind(this)}>
<div className="col-4"
style={{
paddingBottom: "100px",
paddingTop: "20px",
alignItems: "center",
}}>
<label style={{ paddingTop: "5px", marginTop: "40px" }}>
Dataset
<select classname="custom-select"
value={this.state.course}
onChange={this.handleChangeCourse} style={{ paddingTop: "5px", marginTop: "10px" }}
>
{uniqueCouse.map(course => (
<option key={course.id} value={course.dataset}>
{course.dataset}
</option>
))}
</select>
</label>
<div className="col-4">
<button
type="submit"
class="btn"
style={{ marginTop: "" }}
>
ok
</button>
</div>
<div>
{filterDropdown.map(course => (
<div key={course.id} style={{ margin: "10px" }}>
<img src={`${course.path}`} height="80" className="card-img-top img-responsive" alt="img"/>
<br />
</div>
))}
</div>
</div>
<div
className="col-4"
style={{
paddingBottom: "100px",
paddingTop: "20px",
alignItems: "center",
}}
>
<label
className=""
style={{ paddingTop: "5px", marginTop: "40px" }}
>
Model
<select
className="custom-select"
name="example"
value={this.state.model}
onChange={this.handleChange}
style={{ paddingTop: "5px", marginTop: "10px" }}
>
<option>--Select--</option>
{options.map((option) => (
<option
value={option.value}
onChange={(e) => this.setState({ model: e.target.value })}
>
{option.label}
</option>
))}
</select>
</label>
</div>
</form>
</div>
</div>
);
}
}
export default Inference;
this code works perfectly fine i can able to see the results in console log. i want to see the results in new url or stores as new json. kindly help me

Error: Too many re-renders. React limits the number of renders to prevent an infinite loop. because of setState

There might be issue in setFormData, can someone please tell me what mistake i have done that causing rendering in the code. also want to know if there is any mistake in storing image in a state.
Code summary:
I am adding image from input field, and this is taken care by imageSelectedHandler
I want to know is imageUploadHandler required? or even without using I will be able to submit the form along with the image?
I am also adding new input fields, everytime user clicks, add specification button. this is by addClick and removeClick handler
handleChange handler take care of indivisual Input Flield.
Please help someone.
import React, { useState } from "react";
import FormInput from "../Forminput/forminput";
import CustomButton from "../Custombutton/custombutton";
import axios from "axios";
const ProductUpload = () => {
const [formData, setFormData] = useState({
sub_category: null,
product_name: null,
product_image: null,
product_specs: [{ specification: "", specvalue: "" }],
});
const { sub_category, product_name, product_image, product_specs } = formData;
const imageSelectedHandler = (event) => {
setFormData((prevState) => ({
product_image: event.target.files[0],
sub_category: { ...prevState.sub_category },
product_name: { ...prevState.product_name },
product_specs: [
...prevState.product_specs,
{ specification: "", specvalue: "" },
],
}));
};
const imageUploadHandler = () => {
const fd = new FormData();
fd.append("product_image", product_image, product_image.name); //.name is Imp as name is property of file
};
const handleChange = (i, e) => {
const { name, value } = e.target;
product_specs[i] = { ...product_specs[i], [name]: value };
setFormData({ product_specs }); //TO BE CHECKED
};
//to add extra input field
const addClick = () => {
setFormData((prevState) => ({
sub_category: { ...prevState.sub_category },
product_image: { ...prevState.image },
product_name: { ...prevState.product_name },
product_specs: [
...prevState.product_specs,
{ specification: "", specvalue: "" },
],
}));
};
//to remove extra input field
const removeClick = (i) => {
product_specs.splice(i, 1);
setFormData((prevState) => {
return {
sub_category: { ...prevState.sub_category },
product_image: { ...prevState.image },
product_name: { ...prevState.product_name },
product_specs: [
...prevState.product_specs,
{ specification: "", specvalue: "" },
],
};
});
};
const handleSubmit = async (event) => {
event.preventDefault();
const newProduct = {
sub_category,
product_name,
product_image,
product_specs,
};
try {
const config = {
headers: {
"Content-Type": "application/json",
},
};
const body = JSON.stringify(newProduct);
const res = await axios.post("/api/product", body, config);
console.log(res.data);
} catch (error) {
console.error(error.response.data);
}
};
const createUI = () => {
return product_specs.map((el, i) => (
<div key={i} className="inputgroup">
<FormInput
type="text"
name="specification"
handleChange={handleChange}
value={el.specification}
label="specification"
required
customwidth="300px"
></FormInput>
<FormInput
type="text"
name="specvalue"
handleChange={handleChange}
value={el.specvalue}
label="specification values seperated by quomas"
required
></FormInput>
<CustomButton
onClick={removeClick(i)}
type="button"
value="remove"
style={{ margin: "12px" }}
>
Remove
</CustomButton>
</div>
));
};
return (
<div className="container">
<form
action="/upload"
method="post"
className="form"
onSubmit={handleSubmit}
encType="multipart/form-data"
>
<h3 style={{ color: "roboto, sans-serif" }}>
Add new product to the database
</h3>
<div
style={{
display: "flex",
height: "200px",
width: "200px",
border: "2px solid #DADCE0",
borderRadius: "6px",
position: "relative",
}}
>
<input
style={{ display: "none" }}
type="file"
accept="image/*"
onChange={imageSelectedHandler}
ref={(fileInput) => (this.fileInput = fileInput)}
multiple={false}
name="product_image"
/>
<CustomButton onClick={() => this.fileInput.click()}>
Select Image
</CustomButton>
<CustomButton onClick={imageUploadHandler}>Upload</CustomButton>
{/*as per brad- type = "submit" value="submit" this should not be used, file should upload with the form submit */}
<div>
<img
style={{
width: "100%",
height: "100%",
}}
alt="#"
/>
</div>
</div>
{createUI()}
<div>
<CustomButton
onClick={addClick}
type="button"
style={{ margin: "14px" }}
>
Add More Fields
</CustomButton>
<CustomButton type="submit" style={{ margin: "12px" }}>
Upload Product
</CustomButton>
</div>
</form>
</div>
);
};
export default ProductUpload;
code with the changes suggested by #AKX
import React, { useState } from "react";
import FormInput from "../Forminput/forminput";
import CustomButton from "../Custombutton/custombutton";
import axios from "axios";
const ProductUpload = () => {
const [sub_category, setSub_category] = useState({
sub_category: "",
});
const [product_name, setProduct_name] = useState({
product_name: "",
});
const [product_image, setProduct_image] = useState({
product_image: "",
});
const [product_specs, setProduct_specs] = useState({
product_specs: [{ specification: "", specvalue: "" }],
});
const imageSelectedHandler = (event) => {
setProduct_image({ product_image: event.target.files[0] });
};
// const imageUploadHandler = () => {
// const fd = new FormData();
// fd.append("product_image", product_image, product_image.name); //.name is Imp as name is property of file
// };
const handleChange = (i, e) => {
const { name, value } = e.target;
product_specs[i] = { ...product_specs[i], [name]: value };
setProduct_specs({ product_specs }); //TO BE CHECKED
};
//to add extra input field
const addClick = () => {
setProduct_specs({
product_specs: [...product_specs, { specification: "", specvalue: "" }],
});
};
//to remove extra input field
const removeClick = (i) => {
[product_specs].splice(i, 1);
setProduct_specs({
product_specs: [product_specs],
});
};
const handleSubmit = async (event) => {
event.preventDefault();
const newProduct = {
sub_category,
product_name,
product_image,
product_specs,
};
try {
const config = {
headers: {
"Content-Type": "application/json",
},
};
const body = JSON.stringify(newProduct);
const res = await axios.post("/api/product", body, config);
console.log(res.data);
} catch (error) {
console.error(error.response.data);
}
};
const createUI = () => {
return [product_specs].map((el, i) => (
<div key={i} className="inputgroup">
<FormInput
type="text"
name="specification"
handleChange={handleChange}
value={el.specification}
label="specification"
required
customwidth="300px"
></FormInput>
<FormInput
type="text"
name="specvalue"
handleChange={handleChange}
value={el.specvalue}
label="specification values seperated by quomas"
required
></FormInput>
<CustomButton
onClick={removeClick(i)}
type="button"
value="remove"
style={{ margin: "12px" }}
>
Remove
</CustomButton>
</div>
));
};
return (
<div className="container">
<form
action="/upload"
method="post"
className="form"
onSubmit={handleSubmit}
encType="multipart/form-data"
>
<h3 style={{ color: "roboto, sans-serif" }}>
Add new product to the database
</h3>
<div
style={{
display: "flex",
height: "200px",
width: "200px",
border: "2px solid #DADCE0",
borderRadius: "6px",
position: "relative",
}}
>
<input
style={{ display: "none" }}
type="file"
accept="image/*"
onChange={imageSelectedHandler}
ref={(fileInput) => (this.fileInput = fileInput)}
multiple={false}
name="product_image"
/>
<CustomButton onClick={() => this.fileInput.click()}>
Select Image
</CustomButton>
<CustomButton
// onClick={imageUploadHandler}
>
Upload
</CustomButton>
{/*as per brad- type = "submit" value="submit" this should not be used, file should upload with the form submit */}
<div>
<img
style={{
width: "100%",
height: "100%",
}}
alt="#"
/>
</div>
</div>
<FormInput
type="text"
name="sub_category"
handleChange={handleChange}
value={sub_category}
label="select from subcategories"
required
></FormInput>
<FormInput
type="text"
name="product_name"
handleChange={handleChange}
value={product_name}
label="product name"
required
></FormInput>
{createUI()}
<div>
<CustomButton
onClick={addClick}
type="button"
style={{ margin: "14px" }}
>
Add More Fields
</CustomButton>
<CustomButton type="submit" style={{ margin: "12px" }}>
Upload Product
</CustomButton>
</div>
</form>
</div>
);
};
export default ProductUpload;
Ciao, I have never seen an use of prevState in useState hook like that. Basically, when you spread prevState it's like you saying: "keep the same values for all the state elements" then comma, then a list of new values for the state.
So, it's not necessary to re-assign the same value of prevState in current state (because it already have!). So, I think you should modify your code like this:
const imageSelectedHandler = (event) => {
let new_product_specs = formData.product_specs;
new_product_specs.push({ specification: "", specvalue: "" });
setFormData((prevState) => ({
...prevState,
product_image: event.target.files[0],
product_specs: new_product_specs
}));
};
For the question about imageUploadHandler, I don't think is required to submit form. But I'm not 100% sure.

Resources