Not hitting `debugger` statement in `handleOnSubmit` - javascript

I'm having a pretty specific problem in my React with Rails API backend app. I have a Redux form that I am using to create a new object, a real estate listing. The state is changing in my onChange function but when I click submit, the page refreshes and nothing was created. I put debugger inside my handleOnSubmit and it’s not hitting, any ideas?
ListingForm.js:
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { updateListingFormData } from '../actions/listingForm';
import { createListing } from '../actions/listings';
class ListingForm extends Component {
handleOnChange = event => {
const { name, value } = event.target;
const currentListingFormData = Object.assign({}, this.props.listingFormData, {
[name]: value
})
this.props.updateListingFormData(currentListingFormData)
}
handleOnSubmit = (event) => {
debugger;
event.preventDefault()
this.props.createListing(this.props.listingFormData)
}
render() {
const { title, price, location, description, img_url, agent_name, agent_number, agent_email } = this.props.listingFormData;
return (
<div className="ListingForm">
<h3>Add New Listing</h3>
<form onSubmit={(event) => this.handeOnSubmit(event)}>
<label htmlFor="listing_title">Title</label>
<input
type="text"
name="title"
value={title}
onChange={(event) => this.handleOnChange(event)}
placeholder="Listing Title"
/>
<label htmlFor="listing_location">Location</label>
<input
type="text"
name="location"
value={location}
onChange={(event) => this.handleOnChange(event)}
placeholder="Listing City or County"
/>
<label htmlFor="listing_price">Price</label>
<input
type="integer"
name="price"
value={price}
onChange={(event) => this.handleOnChange(event)}
placeholder="Listing Price"
/>
<label htmlFor="listing_description">Description</label>
<input
type="text"
name="description"
value={description}
onChange={(event) => this.handleOnChange(event)}
placeholder="Listing Description"
/>
<label htmlFor="listing_image">Attach Image</label>
<input
type="text"
name="img_url"
value={img_url}
onChange={(event) => this.handleOnChange(event)}
placeholder="Listing Image"
/>
<label htmlFor="agent_name">Listing Agent</label>
<input
type="text"
name="agent_name"
value={agent_name}
onChange={(event) => this.handleOnChange(event)}
placeholder="Agent Name"
/>
<label htmlFor="agent_number">Listing Agent Phone</label>
<input
type="text"
name="agent_number"
value={agent_number}
onChange={(event) => this.handleOnChange(event)}
placeholder="Agent Phone"
/>
<label htmlFor="agent_email">Agent Email</label>
<input
type="text"
name="agent_email"
value={agent_email}
onChange={(event) => this.handleOnChange(event)}
placeholder="Agent Email"
/>
<button type="submit"> Add Listing</button>
</form>
</div>
)
}
}
const mapStateToProps = state => {
return {
listingFormData: state.listingFormData
}
}
export default connect(mapStateToProps, {updateListingFormData,createListing})(ListingForm);

In your form onSubmit you've misspelt handleOnSubmit (you left out the l)

Related

Getting error "Uncaught Error: Objects are not valid as a React child", but I'm not passing objects as children

I'm attempting to map an array of objects, obtained from an axios.get request, as a set of React component children. Here is the full error I'm receiving:
Uncaught Error: Objects are not valid as a React child (found: [object Promise]). If you meant to render a collection of children, use an array instead.
My goal here is to create an Admin component where new shows can be created, and existing shows can be edited and deleted. I've confirmed that the axios request's response.data is an array of objects, and I'm not passing the objects themselves as children. I'm passing them as props to <ShowListing /> components, and I know that this component works with those props. Can someone please help me figure out what's going wrong here?
Here is the code for the Admin component. It seems that the error is occurring from lines 107-113:
import { useState, useEffect } from 'react'
import styles from './Admin.module.css'
import axios from 'axios'
import FormData from 'form-data'
import ShowListing from './ShowListing.js'
const Admin = async () => {
const [formValues, setFormValues] = useState({
eventTitle: null,
location: null,
date: null,
time: null,
ticket: null,
desc: null,
image: null
})
const [currShows, setCurrShows] = useState(null)
useEffect(async () => {
axios.get("http://localhost:4000/getShows").then(response => {
console.log(response.data)
setCurrShows(response.data)
})
})
const handleSubmit = async (e) => {
e.preventDefault()
const formData = new FormData()
// FILE READER
const getImageFile = () => {
return new Promise(resolve => {
const reader = new FileReader()
reader.onload = function () {
resolve(reader.result)
// console.log(`IMAGE FILE:\n ${imageFile}`) // imageFile IS NOT UNDEFINED HERE, BASE64 STRING
}
reader.readAsDataURL(document.getElementById("image").files[0])
})
}
const imageFile = await getImageFile()
Array.from(document.getElementById("form").elements).forEach(element => {
switch (element.name){
case "image":
formData.append(`${element.name}`, imageFile) // UNDEFINED. WHY?
break
case "submit":
break
default:
formData.append(`${element.name}`, element.value)
}
})
console.log([...formData])
try {
const response = axios.post('http://localhost:4000/uploadShow', formData)
console.log(response)
alert('NEW SHOW SUBMITTED')
document.getElementById("form").reset()
} catch (e) {
alert(e)
console.log(e)
}
}
return (
<div>
<div className={styles.main}>
<div className={styles.titleContainer}>
<h1>KMAC ADMIN</h1>
</div>
<div className={styles.formWindow}>
<div className={styles.newShowHeader}>
<h1>New Show</h1>
<form className={styles.showForm} id="form" method="post" encType="multipart/form-data" onSubmit={e => handleSubmit(e)}>
<label htmlFor="eventTitle">Event Title: </label>
<input className={styles.fieldInput} type="text" name="eventTitle" onChange={e => setFormValues({...formValues, eventTitle: e.target.value})}/>
<br />
<label htmlFor="location">Location: </label>
<input className={styles.fieldInput} type="text" name="location"onChange={e => setFormValues({...formValues, location: e.target.value})} />
<br />
<label htmlFor="date">Date: </label>
<input className={styles.fieldInput} type="date" name="date" onChange={e => setFormValues({...formValues, date: e.target.value})}/>
<br />
<label htmlFor="time">Time: </label>
<input className={styles.fieldInput} type="time" name="time" onChange={e => setFormValues({...formValues, time: e.target.value})}/>
<br />
<label htmlFor="ticket">Ticket: </label>
<input className={styles.fieldInput} type="text" name="ticket" onChange={e => setFormValues({...formValues, ticket: e.target.value})}/>
<br />
<textarea name="desc" placeholder="Event Description" rows="8" onChange={e => setFormValues({...formValues, desc: e.target.value})}/>
<br />
<label htmlFor="image">Select Image (15MB or less): </label>
<input type="file" id="image" name="image" accept="image/jpeg" onChange={e => setFormValues({...formValues, image: e.target.files})}/>
<br />
<button className={styles.submit} name="submit" type="submit">Submit</button>
</form>
</div>
</div>
</div>
<div>
{
currShows.map(show => {
return <ShowListing params={show} />
})
}
</div>
</div>
)
}
export default Admin
Here is the code for the ShowListing component:
import { useState } from 'react'
import axios from 'axios'
import styles from './ShowListing.module.css'
// SHOW OBJECT SHAPE:
// eventTitle: null,
// location: null,
// date: null,
// time: null,
// ticket: null,
// desc: null,
// image: null
const ShowListing = (props) => {
// Toggle deletion warning
const [deleteWarning, setDeleteWarning] = useState(false)
const [editForm, setEditForm] = useState(false)
const [formValues, setFormValues] = useState({
eventTitle: null,
location: null,
date: null,
time: null,
ticket: null,
desc: null,
image: null
})
// covert props.params.date to format "year-month-day", call for date input default value
const dateConvert = () => {
const dateArr = props.params.date.split('-')
const year = dateArr.pop()
dateArr.unshift(year)
return dateArr.join('-')
}
// covert props.param.time to 24-hour format, call for time input default value
const timeConvert = () => {
const timeArr = props.params.time.split(' ')
const time = timeArr[0].split(":")
if (timeArr[1] === 'PM')
time[0] = ((parseInt(time[0])) + 12).toString()
if (parseInt(time[0]) < 10)
time[0] = "0" + time[0]
return time.join(":")
}
const handleDelete = () => {
// TODO: delete request with props.params._id
// Alert deletion and reload page
alert(`SHOW DELETED:\n${props.params.eventTitle}`)
window.location.reload()
}
const handleEditSubmit = (e) => {
e.preventDefault()
// TODO: post request for show update with props.params._id
console.log(formValues)
alert(`SHOW EDITED:\n${formValues.eventTitle}\nFORMERLY:\n${props.params.eventTitle}`)
window.location.reload()
}
return (
<div className={styles.temp}>
<div className={styles.container}>
{
deleteWarning &&
<div className={styles.deleteWarning}>
<div><p>Delete this show listing?</p></div>
<div><button className={`${styles.deleteButton} ${styles.deleteYes}`} onClick={handleDelete}>Yes</button></div>
<div><button className={`${styles.deleteButton} ${styles.deleteNo}`} onClick={() => setDeleteWarning(false)}>No</button></div>
</div>
}
<div className={styles.title}>
<p>{props.params.eventTitle}</p>
</div>
<div className={styles.date}>
<p>{`${props.params.date} -- ${props.params.time}`}</p>
</div>
<div className={styles.edit} onClick={() => setEditForm(true)}>
<img src="images/icons8-edit-30.png" />
</div>
<div className={styles.delete} onClick={() => setDeleteWarning(true)}>
<img src="images/icons8-trash-30.png" />
</div>
<br/>
</div>
{
editForm &&
<div className={styles.formContainer}>
<div className={styles.formFrame}>
<form id="editForm" onSubmit={e => handleEditSubmit(e)}>
<label className={styles.formLabel} htmlFor="eventTitle">Event Title: </label>
<br />
<input className={styles.fieldInput} type="text" name="eventTitle" defaultValue={props.params.eventTitle} onChange={e => setFormValues({...formValues, eventTitle: e.target.value})}/>
<br />
<label className={styles.formLabel} htmlFor="location">Location: </label>
<br />
<input className={styles.fieldInput} type="text" name="location" defaultValue={props.params.location} onChange={e => setFormValues({...formValues, location: e.target.value})} />
<br />
<label className={styles.formLabel} htmlFor="date">Date: </label>
<br />
<input className={styles.fieldInput} type="date" name="date" defaultValue={dateConvert()} onChange={e => setFormValues({...formValues, date: e.target.value})}/>
<br />
<label className={styles.formLabel} htmlFor="time">Time: </label>
<br />
<input className={styles.fieldInput} type="time" name="time" defaultValue={timeConvert()} onChange={e => setFormValues({...formValues, time: e.target.value})}/>
<br />
<label className={styles.formLabel} htmlFor="ticket">Ticket: </label>
<br />
<input className={styles.fieldInput} type="text" name="ticket" defaultValue={props.params.ticket} onChange={e => setFormValues({...formValues, ticket: e.target.value})}/>
<br />
<br />
<textarea className={styles.formDesc} name="desc" placeholder="Event Description" rows="8" defaultValue={props.params.desc} onChange={e => setFormValues({...formValues, desc: e.target.value})}/>
<br />
<label className={styles.formLabel} htmlFor="image">Please update image (15MB or less): </label>
<input style={{color: "red"}} type="file" id="image" name="image" accept="image/jpeg" onChange={e => setFormValues({...formValues, image: e.target.files})}/>
<br />
<br />
<button className={styles.submit} name="submit" type="submit">Submit</button>
<button name="cancel" onClick={() => setEditForm(false)}>Cancel</button>
</form>
</div>
</div>
}
</div>
)
}
export default ShowListing
UPDATE:
Per phasma's suggestion, I removed async from the Admin component and the useEffect. This cleared the original error, but now I'm receiving a new error:
Admin.js:107 Uncaught TypeError: Cannot read properties of null (reading 'map')
Why is currShows null when it's being set in the useEffect?
You're marking your Admin component async, which is not valid for a React component. Remove that modifier and the error should clear up.
edit; To answer your new question, currShows is null until the call is completed, which is likely after the first render. You should write something like
currShows === null ? null : currShows.map(show => { /* ... */
to handle that case explicitly. The null could be a loading spinner or something to indicate something's working in the background, but hopefully that helps clear your error.

function to update my form makes checkboxes change from true/ false to say 'on' but need it to toggle true or false

I am having an issue where my change function makes my checkboxes go from either true/false to just be 'on'. All the fields in my form use onInputChange and they all work accept for the checkboxes. So if I type in the text fields it updates properly and saves to my database with no issue but if I click a checkbox no matter the value that it started as it will change to 'on' and gives a cannot convert varchar to int error. I am looking for a new function to update the checkboxes properly and keep the onInputChange one for the text fields.
I did create one like below and it seems to change from true to false properly but 100% clears the rest of the data already in the form.
const onCheckboxChange = e => {
setUser({
active = !active });
console.log(user)
};
import React, { useState, useEffect } from "react";
import axios from "axios";
import { useParams, Link } from "react-router-dom";
const UpdateUser = () => {
const { collectorID } = useParams();
const [user, setUser] = useState({});
const {collectorOptionsID, programBucketID,financeCompanyID, active, firstName, middleInitial, lastName, collectorCode, aging1to15, aging31to45, aging31to60, agingOver60, programBucketA, programBucketB, programBucketC, programBucketSU, financeCompany, debtType } = user;
const onInputChange = e => {
setUser({
...user, [e.target.name]: e.target.value });
console.log(user)
};
useEffect(() => {
loadUser();
}, []);// eslint-disable-line react-hooks/exhaustive-deps
const loadUser = async () => {
const result = await axios.get(`https://support.pawneeleasing.com/PublishedCollectorAPI/api/Collector/${collectorID}`);
setUser(result.data);
console.log(result.data);
};
const onSubmit = async e => {
e.preventDefault();
console.log(active);
await axios.put(process.env.NODE_ENV === 'development' ? `${process.env.REACT_APP_DEV_UPDATE}${collectorID}` : `${process.env.REACT_APP_PRO_UPDATE}${collectorID}`, {
// await axios.put(`https://support.pawneeleasing.com/PublishedCollectorAPI/api/Collector/${collectorID}`, {
collectorID: collectorID,
collectorOptionsID: collectorOptionsID,
programBucketID: programBucketID,
financeCompanyID: financeCompanyID,
active: active,
firstName: firstName,
middleInitial: middleInitial,
lastName: lastName,
collectorCode: collectorCode,
debtType: debtType,
aging1to15: aging1to15,
aging31to45: aging31to45,
aging31to60:aging31to60,
agingOver60: agingOver60,
programBucketA: programBucketA,
programBucketB: programBucketB,
programBucketC: programBucketC,
programBucketSU: programBucketSU,
financeCompany: financeCompany,
});
};
return (
<div className="newUser">
<h1>Update Collector</h1>
<form className="newUserForm" >
<div className="newUserItem">
{/*active or inactive User*/}
<label>active</label>
<div className="newUserCheckboxContainer">
<input
type='checkbox'
name="active"
defaultChecked={active}
onClick={e => onInputChange(e)}
/>
</div>
{/*Collector First Name*/}
<label>First Name</label>
<input
type="text"
name="firstName"
placeholder="First Name"
defaultValue={firstName}
onChange={e => onInputChange(e)}
/>
{/*Collector Middle Initial*/}
<label>Middle Initial</label>
<input
type="text"
name="middleInitial"
placeholder="Middle Initial"
defaultValue={middleInitial}
onChange={e => onInputChange(e)}
/>
{/*Collector Last Name*/}
<label>Last Name</label>
<input
type="text"
name="lastName"
placeholder="Last Name"
defaultValue={lastName}
onChange={e => onInputChange(e)}
/>
{/*Collector Code First Initial Middle Initial Last Initial*/}
<label>Collector Code</label>
<input
type="text"
name="collectorCode"
placeholder="Collector Code"
defaultValue={collectorCode}
onChange={e => onInputChange(e)}
/>
{/*Aging Bucket selection section */}
<label>Aging Bucket</label>
<div className='newUserCheckboxContainer'>
<label className='newUserCheckboxLabel'>1-15<br/>
<input
type='checkbox'
className='AgingBucketCheckbox'
defaultValue={aging1to15}
defaultChecked={aging1to15}
onChange={e => onInputChange(e)}
/></label>
<label className='newUserCheckboxLabel'>31-45<br/>
<input
type='checkbox'
className='AgingBucketCheckbox'
defaultValue={aging31to45}
defaultChecked={aging31to45}
onChange={e => onInputChange(e)}
/></label>
<label className='newUserCheckboxLabel'>31-60<br/>
<input
type='checkbox'
className='AgingBucketCheckboxsm'
defaultValue={aging31to60}
defaultChecked={aging31to60}
onChange={e => onInputChange(e)}
/></label>
<label className='newUserCheckboxLabel'>Over 60<br/>
<input
type='checkbox'
className='AgingBucketCheckboxlg'
defaultValue={agingOver60}
defaultChecked={agingOver60}
onChange={e => onInputChange(e)}
/></label>
</div>
{/*Progam code selection section*/}
<label>Program Bucket</label>
<div className='newUserCheckboxContainer'>
<label className='newUserCheckboxLabel'>A<br/>
<input
type='checkbox'
className='programBucketChecbox'
defaultValue={programBucketA}
defaultChecked={programBucketA}
onChange={e => onInputChange(e)}
/></label>
<label className='newUserCheckboxLabel'>B<br/>
<input
type='checkbox'
className='programBucketChecbox'
defaultValue={programBucketB}
defaultChecked={programBucketB}
onChange={e => onInputChange(e)}
/></label>
<label className='newUserCheckboxLabel'>C<br/>
<input
type='checkbox'
className='programBucketChecbox'
defaultValue={programBucketC}
defaultChecked={programBucketC}
onChange={e => onInputChange(e)}
/></label>
<label className='newUserCheckboxLabel'>SU<br/>
<input
type='checkbox'
className='programBucketChecbox'
defaultValue={programBucketSU}
defaultChecked={programBucketSU}
onChange={e => onInputChange(e)}
/></label>
</div>
{/*Finance Company selection section*/}
<label>Finance Company</label>
<div className='newUserCheckboxContainer'>
<input
type="text"
name="financeCompany"
placeholder="financeCompany"
defaultValue={financeCompany}
onChange={e => onInputChange(e)}
/>
</div>
<label>Debt Type</label>
<div className='newUserCheckboxContainer'>
<input
type="text"
name="debtType"
placeholder="debtType"
defaultValue={debtType}
onChange={e => onInputChange(e)}
/>
</div>
<button type='submit' onClick={(event)=>onSubmit(event)} className="userListAddButton">Update Collector</button>
<Link className="userListGoBackButton" to='/users'>Go Back</Link>
</div>
</form>
</div>
);
}
export default UpdateUser;
You need to copy the rest of user properties by rest operator
const onCheckboxChange = e => {
setUser(prev => ({
...prev,
active: !prev.active
}))
};

React I have an endless loop rendering my edit component

I have two components. My dashbord-component, in which I am dispatching the getAllDropDownRessort, which triggers the findAll function in my dropdownRessortSlice and an edit-component, in which I am dispatching the getDropdownRessort, which triggers the findOne function in the same slice.
When I calling the edit-component, it not ends rendering, and the redux-devtools tell me that it always renders the findAll function.
Thanks for your help.
Here is my dashbord-component:
const DropdownRessorts = () => {
//bring in
const {dropdownRessort, isLoading, isError, message} = useSelector((state)=>state.dropdownRessort);
const dispatch = useDispatch();
useEffect(()=>{
if(isError){
console.log(message);
}
dispatch(getAllDropdownRessort());
return ()=>{
dispatch(reset());
}
}, [dispatch, isError, message]);
//bring out
const [formdata, setFormdata] = useState(
{
lis:[],
videos:[
{
iframe:"",
ressort:"",
timestamp:"",
theme:"",
title:""
},
{
iframe:"",
ressort:"",
timestamp:"",
theme:"",
title:""
},
{
iframe:"",
ressort:"",
timestamp:"",
theme:"",
title:""
}
],
themen:[],
}
);
const {lis, videos,themen} = formdata;
const handleChange = (e)=>{
setFormdata((prevState)=>({
...prevState,
[e.target.name]: e.target.value,
}))
}
const onSubmit = (e)=>{
e.preventDefault();
const dropdownRessortData = {
lis,
videos,
themen,
}
dispatch(createDropdownRessort(dropdownRessortData));
}
if(isLoading){
return <Spinner/>
}
return (
<Container>
<CrudTitleHolder>
<CrudTitle>Dropdown Menü Ressort</CrudTitle>
</CrudTitleHolder>
<DataformDropDownRessort onSubmit={onSubmit}>
{dropdownRessort.length > 0 && <DataHolder>
{dropdownRessort.map((item)=>(
<div key={item._id}>
{console.log(item._id)}
<h4 id="name">{item.name}</h4>
<div id="listenpunkte">Menüpunkte: {item.lis.join(", ")}<span style={{color:"var(--red)"}}> Bitte nur nach Absprache verändern.</span></div>
<VideoWrapper>
<DataVideoholder>
<iframe src={item.videos[0].iframe} title={item.videos[0].title}/>
<h4>{item.videos[0].ressort}</h4>
<h4>{item.videos[0].theme}</h4>
<p>{item.videos[0].title}</p>
</DataVideoholder>
<DataVideoholder>
<iframe src={item.videos[1].iframe} title={item.videos[0].title}/>
<h4>{item.videos[1].ressort}</h4>
<h4>{item.videos[1].theme}</h4>
<p>{item.videos[1].title}</p>
</DataVideoholder>
<DataVideoholder>
<iframe src={item.videos[2].iframe} title={item.videos[0].title}/>
<h4>{item.videos[2].ressort}</h4>
<h4>{item.videos[2].theme}</h4>
<p>{item.videos[2].title}</p>
</DataVideoholder>
</VideoWrapper>
<Themen>Themen: {item.themen.join(", ")}</Themen>
<DataButtonHolder>
<Link to={`/dropdownressortedit/${item._id}`}className="link">
<DataUpdateButton>Update</DataUpdateButton>
</Link>
<DataDeleteButton onClick={()=>dispatch(deleteDropdownRessort(item._id))}>Löschen</DataDeleteButton>
</DataButtonHolder>
</div>
))}
</DataHolder>}
<section className="menupoints" encType="multipart/form-data">
<DataLabel htmlFor="lis_ressorts">Menüpunkte Ressorts</DataLabel>
<DataInput type="text" name="lis_ressorts" id="lis_ressorts" value={lis} onChange={handleChange}/>
</section>
<div className="videos">
<section className="video_1">
<DataLabel htmlFor="ressortvideo_1_iframe">Video 1</DataLabel>
<DataInput type="file" name="ressortvideo_1_iframe" id="video_1_iframe"
style={{background:"var(--blue)", color:"var(--white)"}}
value={videos[0].iframe} onChange={handleChange}/>
<DataLabel htmlFor="video_1_ressort">Video 1 Ressortzuordnung</DataLabel>
<DataInput type="text" name="video_1_ressort" id="video_1_ressort" value={videos[0].ressort} onChange={handleChange}/>
<DataLabel htmlFor="video_1_theme">Video 1 Themenzuordnung</DataLabel>
<DataInput type="text" name="video_1_theme" id="video_1_theme" value={videos[0].theme} onChange={handleChange}/>
<DataLabel htmlFor="video_1_title">Video 1 Titelzuordnung</DataLabel>
<DataInput type="text" name="video_1_title" id="video_1_title" value={videos[0].title} onChange={handleChange}/>
</section>
<section className="video_2">
<DataLabel htmlFor="ressortvideo_2_iframe">Video 2</DataLabel>
<DataInput type="file" name="ressortvideo_2_iframe" id="video_2_iframe"
style={{background:"var(--blue)", color:"var(--white)"}}
value={videos[1].iframe} onChange={handleChange}/>
<DataLabel htmlFor="video_2_ressort">Video 2 Ressortzuordnung</DataLabel>
<DataInput type="text" name="video_1_ressort" id="video_2_ressort" value={videos[1].ressort} onChange={handleChange}/>
<DataLabel htmlFor="video_2_theme">Video 2 Themenzuordnung</DataLabel>
<DataInput type="text" name="video_2_theme" id="video_2_theme" value={videos[1].theme} onChange={handleChange}/>
<DataLabel htmlFor="video_2_title">Video 2 Titelzuordnung</DataLabel>
<DataInput type="text" name="video_2_title" id="video_2_title" value={videos[1].title} onChange={handleChange}/>
</section>
<section className="video_3">
<DataLabel htmlFor="ressortvideo_3_iframe">Video 3</DataLabel>
<DataInput type="file" name="ressortvideo_3_iframe" id="video_3_iframe"
style={{background:"var(--blue)", color:"var(--white)"}}
value={videos[2].iframe} onChange={handleChange}/>
<DataLabel htmlFor="video_3_ressort">Video 3 Ressortzuordnung</DataLabel>
<DataInput type="text" name="video_3_ressort" id="video_3_ressort" value={videos[2].ressort} onChange={handleChange}/>
<DataLabel htmlFor="video_3_theme">Video 3 Themenzuordnung</DataLabel>
<DataInput type="text" name="video_3_theme" id="video_3_theme" value={videos[2].theme} onChange={handleChange}/>
<DataLabel htmlFor="video_3_title">Video 3 Titelzuordnung</DataLabel>
<DataInput type="text" name="video_3_title" id="video_3_title" value={videos[2].title} onChange={handleChange}/>
</section>
</div>
<section className="themen">
<DataLabel htmlFor="themen_ressorts">Themen</DataLabel>
<DataInput type="text" name="themen_ressorts" id="themen_ressorts" value={themen} onChange={handleChange}/>
</section>
<DataButtonHolder>
<DataSendButton type="submit">Absenden</DataSendButton>
</DataButtonHolder>
</DataformDropDownRessort>
</Container>
)
}
export default DropdownRessorts
Here is my edit-component:
const DropdownRessortEdit = () => {
const dispatch = useDispatch();
const {dropdownRessort, isLoading, isError, message} = useSelector((state)=>state.dropdownRessort);
const { id } = useParams();
const [data, setData] = useState({
lis: [],
videos:[
{
iframe:"",
ressort:"",
theme:"",
title:"",
},
{
iframe:"",
ressort:"",
theme:"",
title:"",
},
{
iframe:"",
ressort:"",
theme:"",
title:"",
},
],
themen:[],
})
const {lis, videos, themen} = data;
useEffect(()=>{
if(isError){
window.alert(message);
}
dispatch(getDropdownRessort(id));
return ()=>{
dispatch(reset());
}
}, [dispatch, isError, message, id]);
const updateData = (value)=>{
return setData((prev) =>{
return { ...prev, ...value}
})
}
const onSubmit = (e)=>{
e.preventDefault();
const updateDropdownRessortData = {
lis,
videos,
themen,
}
dispatch(updateDropdownRessort(updateDropdownRessortData));
}
if(isLoading){
return <Spinner/>
}
return (
<Container>
<Navbar/>
<TitleHolder>
<Title>Update DropdownRessort</Title>
</TitleHolder>
<ContentHolder>
<UpdateForm onSubmit={onSubmit} encType="multipart/form-data">
{dropdownRessort.length > 0 && <DataHolder>
{dropdownRessort.map((item)=>(
<div key={item._id}>
<Label htmlFor="name">Name</Label>
<Input type="text" name="name" id="name" value={item.name} onChange={(e)=>updateData({name: e.target.value})}/>
<Label htmlFor="lis">MenüPunkte</Label>
<Input type="text" name="lis" id=""lis value={item.lis.join(", ")} onChange={(e)=>updateData({lis: e.target.value})}/>
<VideoWrapper>
<VideoSection>
<Label htmlFor="ressortvideo_1_iframe">Video 1 update</Label>
<Input type="text" name="ressortvideo_1_iframe" id="iframe" value={item.videos[0].iframe} onChange={(e)=>updateData({iframe: e.target.value})}/>
<Label htmlFor="ressort">Ressort</Label>
<Input type="text" name="ressort" id="ressort" value={item.videos[0].ressort} onChange={(e)=>updateData({ressort: e.target.value})}/>
<Label htmlFor="theme">Thema</Label>
<Input type="text" name="theme" id="theme" value={item.videos[0].theme} onChange={(e)=>updateData({theme: e.target.value})}/>
<Label htmlFor="title">title</Label>
<Input type="text" name="title" id="title" value={item.videos[0].title} onChange={(e)=>updateData({title: e.target.value})}/>
</VideoSection>
<VideoSection>
<Label htmlFor="ressortvideo_2_iframe">Video 2 update</Label>
<Input type="text" name="ressortvideo_2_iframe" id="iframe" value={data.videos[1].iframe} onChange={(e)=>updateData({iframe: e.target.value})}></Input>
<Label htmlFor="ressort">Ressort</Label>
<Input type="text" name="ressort" id="ressort" value={item.videos[1].ressort} onChange={(e)=>updateData({ressort: e.target.value})}/>
<Label htmlFor="theme">Thema</Label>
<Input type="text" name="theme" id="theme" value={item.videos[1].theme} onChange={(e)=>updateData({theme: e.target.value})}/>
<Label htmlFor="title">title</Label>
<Input type="text" name="title" id="title" value={item.videos[1].title} onChange={(e)=>updateData({title: e.target.value})}/>
</VideoSection>
<VideoSection>
<Label htmlFor="ressortvideo_3_iframe">Video 3 update</Label>
<Input type="text" name="ressortvideo_3_iframe" id="iframe" value={item.videos[2].iframe} onChange={(e)=>updateData({iframe: e.target.value})}></Input>
<Label htmlFor="ressort">Ressort</Label>
<Input type="text" name="ressort" id="ressort" value={item.videos[2].ressort} onChange={(e)=>updateData({ressort: e.target.value})}/>
<Label htmlFor="theme">Thema</Label>
<Input type="text" name="theme" id="theme" value={item.videos[2].theme} onChange={(e)=>updateData({theme: e.target.value})}/>
<Label htmlFor="title">title</Label>
<Input type="text" name="title" id="title" value={item.videos[2].title} onChange={(e)=>updateData({title: e.target.value})}/>
</VideoSection>
</VideoWrapper>
<Label htmlFor="themen">Themen</Label>
<Input type="text" name="themen" id="themen" value={item.themen} onChange={(e)=>updateData({themen: e.target.value})}/>
<ButtonHolder>
<UpdateButton type="submit">Update</UpdateButton>
</ButtonHolder>
</div>
))}
</DataHolder>
}
</UpdateForm>
</ContentHolder>
<Footer/>
</Container>
)
}
export default DropdownRessortEdit
Try to remove dispatch from the dependencies in useEffect hook.
Because you want to fetch dispatch only when the component mount, not each time dispatch is changed.
So, in your code case, it will change dispatch which will re-trigger the hook which will fetch dispatch again which will change dispatch causes the hook to re-trigger and so on .. causing Infinity Loop.
You can try to put dispatch in a React.useCallback function as shown in this example w3school React.useCallback

How to use the info from a component on another component

I am trying to create a payment system in my application.
I have a payment form(paymentForm.js) and it contains the payment information(cardnumber, cvv, expiry...). Is there any way that I can get these information on another component(checkoutPage.js)? Do you have any advice?
Below is my paymentForm.js:
export default class PaymentForm extends React.Component {
state = {
cvv: '',
expiry: '',
focus: '',
name: '',
number: '',
};
handleInputFocus = (e) => {
this.setState({ focus: e.target.name });
}
handleInputChange = (e) => {
const { name, value } = e.target;
this.setState({ [name]: value });
}
render() {
return (
<View>
<Cards id="PaymentForm"
cvc={this.state.cvc}
expiry={this.state.expiry}
focused={this.state.focus}
name={this.state.name}
number={this.state.number}
/>
<form style={{}}>
<input
type="tel"
name="number"
placeholder="Card Details"
maxLength="16"
preview='true'
onChange={this.handleInputChange}
onFocus={this.handleInputFocus}
/>
<br/>
<input
type="text"
name="name"
placeholder="Holder Name"
onChange={this.handleInputChange}
onFocus={this.handleInputFocus}
/>
<br/>
<input
type="tel"
name="expiry"
placeholder="Expiration"
maxLength="4"
onChange={this.handleInputChange}
onFocus={this.handleInputFocus}
/>
<br/>
<input
type="tel"
name="cvc"
placeholder="CVV"
maxLength="5"
onChange={this.handleInputChange}
onFocus={this.handleInputFocus}
/>
<br/>
<input
type="tel"
name="zipcode"
placeholder="ZIP Code"
maxLength="5"
onChange={this.handleInputChange}
onFocus={this.handleInputFocus}
/>
</form>
</View>
);
}
}
You should create a file CheckOut.js and give card information via props. There is also another way to do it by creating a class named 'Checkout' and creating static methods inside.

How to make onChange tracking function in functional component as in class component

Here is my class component
handleChange =(e) => {
this.setState({
[e.target.id]: e.target.value
})
}
<div className="input-field">
<label htmlFor="email">Email</label>
<input type="email" id="email" onChange={this.handleChange}/>
</div>
<div className="input-field">
<label htmlFor="password">Password</label>
<input type="password" id="password" onChange={this.handleChange}/>
</div>
As you can see we can track all the input with one function component.
But how to get the same result as that inside the functional component?
Now I am setting state for each element.
<div className="input-field">
<label htmlFor="email">Email</label>
<input type="email" id="email" onChange={e =>setEmail(e.target.value)}/>
</div>
<div className="input-field">
<label htmlFor="password">Password</label>
<input type="password" id="password" onChange={e => setPassword(e.target.value)}/>
</div>
The update is similar. Given some state, data for example, then a handler may look like:
const handleChange = (e) => {
const { id, value } = e.target;
setData((data) => ({
...data,
[id]: value
}));
};
Use a functional state update to spread in the existing state and use the input's id and value from the onChange event to update that section of state.
Full code example
function App() {
const [data, setData] = useState({});
const handleChange = (e) => {
const { id, value } = e.target;
setData((data) => ({
...data,
[id]: value
}));
};
return (
<div className="App">
<div className="input-field">
<label htmlFor="email">Email</label>
<input type="email" id="email" onChange={handleChange} />
</div>
<div className="input-field">
<label htmlFor="password">Password</label>
<input type="password" id="password" onChange={handleChange} />
</div>
<div>Email: {data.email}</div>
<div>Password: {data.password}</div>
</div>
);
}
declare one state containing both email and pasword for your functional component as below :
let [loginInfo, setLoginInfo] = useState({email:'',password:''})
handleChange =(e) => {
setLoginInfo({
...loginInfo,
[e.target.id]: e.target.value
})
}
you form
<div className="input-field">
<label htmlFor="email">Email</label>
<input type="email" id="email" onChange={handleChange}/>
</div>
<div className="input-field">
<label htmlFor="password">Password</label>
<input type="password" id="password" onChange={handleChange}/>
</div>
You can create object of form input and assign it to a state like below
const [formInput, setFormInput] = useState({
email: "",
password: ""
});
And set it like this
const handleChange = (e) => {
setFormInput((prevState) => ({
...prevState,
[e.target.id]: e.target.value
}));
};
See this codesandbox code
const [input, setInput] = useState({email:"", password:""})
<div className="input-field">
<label htmlFor="email">Email</label>
<input type="email" id="email" value={input.email}
onChange={e => setInput({...input,[e.target.id]: e.target.value}}/>
</div>
<div className="input-field">
<label htmlFor="password">Password</label>
<input type="password" id="password" value={input.password}
onChange={e => setInput({...input,[e.target.id]: e.target.value}}/>
</div>
You can try this code.
In this way you can handle both inputs using same state without handler

Categories