i am working on an App that has an input field and a dropdown. The input field is for the event title and the dropdown has options for the type of event. When I click submit, I want to submit the value of both the event title and the selected dropdown value and render both as one list as I have in the images below.
But when I submit, only the event title is rendered. How can I include the event type too? Can I save the value of the selected dropdown in same array as the event title? Here's my code below:
EventListForm.jsx
import React from "react";
import { v4 as uuidv4 } from "uuid";
const EventListForm = ({
newEvent,
setNewEvent,
events,
setEventList,
}) => {
const handleInputChange = (event) => {
setNewEvent(event.target.value);
};
const submitEvent = (event) => {
event.preventDefault();
setEventList([...events, { id: uuidv4(), title: newEvent, type: newEvent}]);
};
return (
<form>
<div>
<input
type="text"
placeholder="Event title"
onChange={handleInputChange}
/>
</div>
<select onChange={handleInputChange}>
<option value="Birthday">Option 1</option> {" "}
<option value="Graduation">Option 2</option>
</select>
<div>
<button
type="submit"
onClick={submitEvent}
>
Submit
</button>
</div>
</form>
);
};
export default EventListForm;
EventList.jsx
import React from "react";
const EventList = ({ events, setEventList}) => {
return (
<div>
{events.map((event) => (
<li key={event.id}>
<input
type="text"
value={event.title}
value={event.type}
onChange={(event) => event.preventDefault()}
/>
</li>
))}
</div>
);
};
export default EventList;
Events.js
import React, {useState } from "react";
import EventListForm from "./EventForm";
import EventList from "./EventList";
const EventReminder = () => {
const [newEvent, setNewEvent] = useState("");
const [events, setEventList] = useState([]);
return (
<div>
<div>
<div>
<Header />
</div>
<div>
<EventListForm
newEvent={newEvent}
setNewEvent={setNewEvent}
events={events}
setEventList={setEventList}
/>
</div>
<div>
<EventList events={events} setEventList={setEventList} />
</div>
</div>
</div>
);
};
export default EventReminder;
CodePudding user response:
This is happening to you because you are currently overriding the same state of newEvent
in each of the input fields, I corrected your code by changing the value of newEvent
to an object that contains a key for title
and for type
(note that I added a name attribute
in the inputs, and when submitting the form takes for each of the values the appropriate value from the state
const handleInputChange = (event) => {
setNewEvent({ [event.currentTarget.name]: event.target.value });
};
const submitEvent = (event) => {
event.preventDefault();
setEventList([...events, { id: uuidv4(), title: newEvent.title, type: newEvent.type}]);
};
return (
<form>
<div>
<input
type="text"
name="title"
placeholder="Event title"
onChange={handleInputChange}
/>
</div>
<select onChange={handleInputChange} name="type">
<option value="Birthday">Option 1</option> {" "}
<option value="Graduation">Option 2</option>
</select>
<div>
<button
type="submit"
onClick={submitEvent}
>
Submit
</button>
</div>
</form>
);
};
CodePudding user response:
Theres some stuff to clean up here:
- The form state of
EventListForm
really should be local to that component. There is no need for it to be higher up, it overcomplicates and is over-scoping. - The form shouldnt really directly edit the event list state, instead it should pass up the event and do the merging in the parent (makes more sense to keep the concerns there).
- The state merge needs to use the callback form of setState or you can get weird bugs when deriving state from a previous value.
- You shouldnt use a click handler on submit button, use
onSubmit
instead the it will work properly when pressing enter etc.
import React from "react";
const EventListForm = ({
onSubmit
}) => {
const [title, setTitle] = useState("")
const [type, setType] = useState("")
return (
<form onSubmit={() => onSubmit({title, type})}>
<div>
<input
type="text"
placeholder="Event title"
onChange={(e) => setTitle(e.target.value)}
/>
</div>
<select onChange={(e) => setType(e.target.value)}>
<option value="Birthday">Option 1</option> {" "}
<option value="Graduation">Option 2</option>
</select>
<div>
<button
type="submit"
>
Submit
</button>
</div>
</form>
);
};
export default EventListForm;
import React, {useState } from "react";
import EventListForm from "./EventForm";
import EventList from "./EventList";
import { v4 as uuidv4 } from "uuid";
const EventReminder = () => {
const [events, setEventList] = useState([]);
return (
<div>
<div>
<div>
<Header />
</div>
<div>
<EventListForm
onSubmit={(event) => setEventList(prevEvents=> [...prevEvents, {id: uuidv4(), ...event}])}
/>
</div>
<div>
<EventList events={events} setEventList={setEventList} />
</div>
</div>
</div>
);
};
export default EventReminder;
import React from "react";
const EventList = ({ events}) => {
return (
<div>
{events.map((event) => (
<li key={event.id}>
<input
type="text"
value={event.title}
disabled
/>
<select disabled name="type">
<option value="Birthday" selected={event.type === "Birthday"}>Option 1</option>
<option value="Graduation" selected={event.type === "Graduation"}>Option 2</option>
</select>
</li>
))}
</div>
);
};
export default EventList;