Search code examples
reactjsfunctioninputcrudreact-context

How save input values and checked information in state?


I made such a project through context. But I can't save the values of checkbox and select options in memory. All other inputs work correctly. CRUD operations are fine, but when I select and confirm the gender, then when I try to edit the details of that contact, the gender of the contact is not visible. Also, the ``I want to receive information'' button at the bottom does not appear checked.

import React, { useState } from "react";
import { useContext } from "react";
import { GlobalContext } from "../../context/GlobalState";
import { useNavigate } from "react-router-dom";
import { NavLink } from "react-router-dom";
import { v4 as uuidv4 } from 'uuid';
const Form = () => {
  const { ADD_CONTACT } = useContext(GlobalContext);
  const [contact, setContact] = useState({
    id: uuidv4(),
    name: "",
    surname: "",
    fatherName: "",
    specialty: "",
    email: "",
    gender: "",
    updatesNotification:''
  });

  
  const { name, surname, fatherName, specialty, email } = contact;

  let history = useNavigate();

  const onSubmit = (e) => {
    e.preventDefault();
    if (contact) {
      ADD_CONTACT(contact);
      history("/contacts");
      console.log(contact);
    }
  };

  

  return (
    <form onSubmit={onSubmit}>
      <div class="mb-3 row">
        <label class="col-sm-2 col-form-label">Name</label>
        <div class="col-sm-10">
          <input
            class="form-control"
            name="name"
            required
            value={name}
            onChange={(e) =>
              setContact({ ...contact, [e.target.name]: e.target.value })
            }
          />
        </div>
      </div>

      <div class="mb-3 row">
        <label class="col-sm-2 col-form-label">Surname</label>
        <div class="col-sm-10">
          <input
            class="form-control"
            name="surname"
            required
            value={surname}
            onChange={(e) =>
              setContact({ ...contact, [e.target.name]: e.target.value })
            }
          />
        </div>
      </div>

      <div class="mb-3 row">
        <label class="col-sm-2 col-form-label">Father Name</label>
        <div class="col-sm-10">
          <input
            class="form-control"
            name="fatherName"
            required
            value={fatherName}
            onChange={(e) =>
              setContact({ ...contact, [e.target.name]: e.target.value })
            }
          />
        </div>
      </div>

      <div class="mb-3 row">
        <label class="col-sm-2 col-form-label">Email</label>
        <div class="col-sm-10">
          <input
            class="form-control"
            name="email"
            required
            value={email}
            onChange={(e) =>
              setContact({ ...contact, [e.target.name]: e.target.value })
            }
          />
        </div>
      </div>

      <div class="mb-3 row">
        <label class="col-sm-2 col-form-label">Specialty</label>
        <div class="col-sm-10">
          <input
            class="form-control"
            name="specialty"
            required
            value={specialty}
            onChange={(e) =>
              setContact({ ...contact, [e.target.name]: e.target.value })
            }
          />
        </div>
      </div>

      <div className="mb-3 row">
        <label class="col-sm-2 col-form-label">Job</label>
        <div className="col-sm-10 d-flex justify-content-center align-items-center">
          <select class="form-select" aria-label="Default select example">
            <option selected>Bakalavr</option>
            <option value="1">One</option>
            <option value="2">Two</option>
            <option value="3">Three</option>
          </select>
        </div>
      </div>

      <div className="mb-3 row">
        <label class="col-sm-2 col-form-label">Gender</label>
        <div className="col-sm-10">
          <div class="form-check form-check-inline ">
            <input
              class="form-check-input"
              type="radio"
              name="gender"
              value="male"
              onChange={(e) =>
                setContact({ ...contact, [e.target.name]: e.target.value })
              }
            />
            <label class="form-check-label">Kisi</label>
          </div>
          <div class="form-check form-check-inline">
            <input
              class="form-check-input"
              type="radio"
              name="gender"
              value="female"
              onChange={(e) =>
                setContact({ ...contact, [e.target.name]: e.target.value })
              }
            />
            <label class="form-check-label">Female</label>
          </div>
        </div>
      </div>

      <div class="form-check mb-3">
        <input class="form-check-input" type="checkbox" />
        <label class="form-check-label" for="flexCheckDefault">
        I want to be notified of updates
        </label>
      </div>

      <button type="submit" class="btn btn-primary">
        Create a new contact
      </button>
      <NavLink to="/contacts" className="btn btn-danger m-2">
        Cancel
      </NavLink>
    </form>
  );
};

export default Form;

import React from "react";
import { NavLink } from "react-router-dom";
import { useContext, useState, useEffect } from "react";
import { useNavigate, useParams } from "react-router-dom";
import { GlobalContext } from "../../context/GlobalState";

const EditContactForm = () => {

  const { contacts, UPDATE_CONTACT } = useContext(GlobalContext);

  const [selectedContact, setSelectedContact] = useState({
    id: "",
    name: "",
    surname: "",
    fatherName: "",
    specialty: "",
    email: "",
    gender: "",
  });
  const history = useNavigate();

  const {id} = useParams();

  useEffect(() => {
    const userId = id;
    const selectedContact = contacts.find((user) => String(user.id) === userId);
    if (selectedContact) {
      setSelectedContact(selectedContact);
    } 
  }, [id, contacts]);

  function onSubmit(e) {
    e.preventDefault();
    UPDATE_CONTACT(selectedContact);
    console.log("new user edited:", selectedContact);
    history("/contacts");
  }

  const handleOnChange = (e) => {
    setSelectedContact(selectedContact => ({
      ...selectedContact,
      [e.target.name]: e.target.value
    }));
  };
  return (
    <div>
      <form onSubmit={onSubmit}>
        <div class="mb-3 row">
          <label class="col-sm-2 col-form-label">Name</label>
          <div class="col-sm-10">
            <input
              class="form-control"
              name="name"
              required
              value={selectedContact?.name ?? ''}
              onChange={handleOnChange}
            />
          </div>
        </div>

        <div class="mb-3 row">
          <label class="col-sm-2 col-form-label">Surname</label>
          <div class="col-sm-10">
            <input
              class="form-control"
              name="surname"
              required
              value={selectedContact?.surname ?? ''}
              onChange={handleOnChange}
            />
          </div>
        </div>

        <div class="mb-3 row">
          <label class="col-sm-2 col-form-label">Father Name</label>
          <div class="col-sm-10">
            <input
              class="form-control"
              name="fatherName"
              required
              value={selectedContact?.fatherName ?? ''}
              onChange={handleOnChange}
            />
          </div>
        </div>

        <div class="mb-3 row">
          <label class="col-sm-2 col-form-label">Email</label>
          <div class="col-sm-10">
            <input
              class="form-control"
              name="email"
              required
              value={selectedContact?.email ?? ''}
              onChange={handleOnChange}
            />
          </div>
        </div>

        <div class="mb-3 row">
          <label class="col-sm-2 col-form-label">Specialty</label>
          <div class="col-sm-10">
            <input
              class="form-control"
              name="specialty"
              required
              value={selectedContact?.specialty ?? ''}
              onChange={handleOnChange}
            />
          </div>
        </div>

        <div className="mb-3 row">
          <label class="col-sm-2 col-form-label">Vezife</label>
          <div className="col-sm-10 d-flex justify-content-center align-items-center">
            <select class="form-select" aria-label="Default select example">
              <option selected>Bakalavr</option>
              <option value="1">One</option>
              <option value="2">Two</option>
              <option value="3">Three</option>
            </select>
          </div>
        </div>

        <div className="mb-3 row">
          <label class="col-sm-2 col-form-label">Gender</label>
          <div className="col-sm-10">
            <div class="form-check form-check-inline ">
              <input
                class="form-check-input"
                type="radio"
                name="gender"
                required
                value="male"
                onChange={handleOnChange}
              />
              <label class="form-check-label">Male</label>
            </div>
            <div class="form-check form-check-inline">
              <input
                class="form-check-input"
                type="radio"
                name="gender"
                value="female"
                onChange={handleOnChange}
              />
              <label class="form-check-label">Female</label>
            </div>
          </div>
        </div>

        <div class="form-check mb-3">
          <input class="form-check-input" type="checkbox" />
          <label class="form-check-label" for="flexCheckDefault">
          I want to be notified of updates
          </label>
        </div>

        <button type="submit" class="btn btn-primary">
          Update a contact
        </button>
        <NavLink to="/contacts" className="btn btn-danger m-2">
          Cancel
        </NavLink>
      </form>
    </div>
  );
};

export default EditContactForm;

enter image description here

enter image description here

sandbox: https://codesandbox.io/s/task1-w5zvg4?file=/src/App.js


Solution

  • When working with checkbox you have to look for e.target.checked to access if it is checked or not.

    You can try something like this:

        <div class="form-check form-check-inline">
                <input
                  class="form-check-input"
                  type="radio"
                  name="gender"
                  id="female"
                  checked={contact.gender === "female"}
                  onChange={(e) =>
                    setContact({ ...contact, [e.target.name]: e.target.checked ? e.target.id : "" })
                  }
                />
                <label htmlFor="female" class="form-check-label">Female</label>
    </div>
    

    For the select, you can achieve this like this:

    const selectOptions = [
      {label: "One", value: 1},
      {label: "Two", value: 2},
      {label: "Three", value: 3},
    ]
    
    const Test = () => {
      const onChange = (e) => setContact({ ...contact, [e.target.name]: e.target.value })
        return <>
        <label class="col-sm-2 col-form-label">Job</label>
        <div className="col-sm-10 d-flex justify-content-center align-items-center">
          <select value={contact.test} onChange={onChange} name="test" class="form-select" aria-label="Default select example">
            {selectOptions.map(item => (
              <option key={item.value} value={item.value}>{item.label}</option>
            ))}
          </select>
        </div>
        </>
    }