Home > Net >  Render Input and Dropdown Value in same DIV using UseState
Render Input and Dropdown Value in same DIV using UseState

Time:10-09

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:

enter image description here

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;
  • Related