Home > Blockchain >  React Form loses input on reload
React Form loses input on reload

Time:07-04

im having trouble with a project of mine with the useState hook. This is for a declaration of an event.

This component can be opened from a list of all the other declas{ which works fine} and then everything shows however if you reload the page/open it from a link nothing shows up in the following fields even when it does get the decla using using the useEffect hoop(at least it logs it out to the console)

TLDR; when component called/opened from a list it works and loads all the data but when the page is reloaded it is all lost and doesnt load it again with useState

ive taken the liberty to reduces the amount of data show as it is a pretty long file already.

import { useContext, useEffect, useState } from "react";
import { useNavigate, useParams } from "react-router-dom";
import Select from "react-select";
import CreatableSelect from "react-select/creatable";
import DeclaContext from "../../context/DeclaContext";
import LedenContext from "../../context/LedenContext";
import EventContext from "../../context/EventContext";

export const DeclaFrom = () => {
  let { id } = useParams();
  const navigate = useNavigate();
  const { user, leden } = useContext(LedenContext);
  const { events } = useContext(EventContext);
  let { declas, GET, GET_decla, POST, PUT, DELETE, boekstuks, POST_boekstuk } =
    useContext(DeclaContext);
  // useEffect(() => {
  //   const get = async () => {
  //     await GET();
  //     const data = await GET_decla(id);
  //     setDecla(data);
  //   };
  //   get();
  //   // eslint-disable-next-line
  // }, [id]);
  console.log(declas?.find((de) => (de.id === id ? true : false)));
  const [decla, setDecla] = useState(declas?.find((de) => de.id === id));
  const [event, setEvent] = useState(decla && decla?.event);
  const [owner, setOwner] = useState(decla ? decla?.owner : user.lid_id);
  const [content, setContent] = useState(decla ? decla?.content : "");
  const [total, setTotal] = useState(decla ? decla?.total : 0);
  const [receipt, setReceipt] = useState(decla && decla?.receipt);
  const [boekstuk, setBoekstuk] = useState(decla ? decla?.boekstuk : "");
  const [content_ficus, setContent_ficus] = useState(
    decla ? decla?.content_ficus : ""
  );
  const optionsLeden = [
    { label: "Select All", value: "all" },
    ...leden?.map((lid) => ({
      value: lid.id,
      label: lid?.initials,
    })),
  ];
  const [defaultValues, setDefaultValues] = useState(
    decla
      ? decla?.present?.map((pres) =>
          optionsLeden?.find((x) => x.value === pres)
        )
      : []
  );
  const optionsBoekstuk = boekstuks?.map((boekstuk) => ({
    value: boekstuk?.id,
    label: boekstuk?.name,
  }));
  const optionsEvents = events?.map((event) => ({
    value: event.id,
    label: event.description   " "   event.start_date,
  }));
  async function createBookstuk(inputValue) {
    const BSid = await POST_boekstuk({ name: inputValue });
    setBoekstuk(optionsBoekstuk?.find((x) => x.id === BSid)?.value);
  }
  const onDelete = (e) => {
    e.preventDefault();
    DELETE({
      id,
    });
    setDeleted(true);
  };
  const onSubmit = (e) => {
    // if (!event | !content | !total | !present) {
    //   alert("Je moet een evenement kiezen");
    //   return;
    // }
    e.preventDefault();
    if (decla) {
      PUT({
        id,
        event,
        content,
        total,
        receipt,
        boekstuk,
      });
      navigate("/declas");
    } else {
      POST({
        event,
        content,
        total,
        receipt,
        boekstuk,
      });
    }
    setDeleted(false);
  };
  return (
    <div className="columns">
      <div className="column is-half is-offset-3">
        <form>
          <table>
            <tbody>
              {user.roles.includes("Fiscus") && (
                <tr>
                  <th>
                    <label htmlFor="id_lid">Lid:</label>
                  </th>

                  <td className="field">
                    <Select
                      defaultValue={optionsLeden?.find(
                        (x) => x.value === owner
                      )}
                      options={optionsLeden?.filter(
                        (x) => !["all", 19900].includes(x.value)
                      )}
                      name="owner"
                      id="id_present"
                      onChange={(e) => {
                        setOwner(e.value);
                      }}
                    />
                  </td>
                </tr>
              )}
              <tr>
                <th>
                  <label htmlFor="id_event">Event:</label>
                </th>
                <td className="field">
                  <Select
                    defaultValue={optionsEvents?.find(
                      (x) => x.value === event?.id
                    )}
                    options={optionsEvents}
                    name="event"
                    onChange={(e) => {
                      setEvent(e.value);
                    }}
                  />
                </td>
              </tr>

              <tr>
                <th>
                  <label htmlFor="id_total">Total:</label>
                </th>
                <td className="field">
                  <input
                    type="number"
                    onChange={(e) => setTotal(e.target.value)}
                    name="total"
                    value={total}
                    step="any"
                    className="input"
                    required
                    id="id_total"
                  />
                </td>
              </tr>

              <tr>
                <th>
                  <label htmlFor="id_present">Present:</label>
                </th>
                <Select
                  isMulti
                  value={defaultValues}
                  options={optionsLeden}
                  required
                  name="present"
                  id="id_present"
                  onChange={(e) => {
                    if (e.some((val) => val.value === "all")) {
                      setPresent(
                        optionsLeden
                          ?.filter((x) => x.value !== "all")
                          .map((x) => x.value !== "all" && x.value)
                      ); // change the value going to the API

                      setDefaultValues(
                        optionsLeden
                          ?.filter((x) => x.value !== "all")
                          .map((x) => x.value !== "all" && x)
                      ); // change the values displayed
                    } else {
                      setPresent(e?.map((x) => x.value)); // change the value going to the API
                      setDefaultValues(e?.map((x) => x)); // change the values displayed
                    }
                  }}
                />
              </tr>

              <tr>
                <th>
                  <label htmlFor="id_receipt">Receipt:</label>
                </th>
                <td className="field">
                  <input
                    type="file"
                    name="receipt"
                    required
                    accept="image/*"
                    onChange={(e) => {
                      setReceipt(e.target.files[0]);
                    }}
                    className="input"
                    id="id_receipt"
                  />
                </td>
              </tr>

              <tr>
                <th>
                  <label htmlFor="id_boekstuk">Boekstuk:</label>
                </th>
                <td className="field">
                  <CreatableSelect
                    defaultValue={optionsBoekstuk?.find(
                      (x) => x.value === boekstuk
                    )}
                    options={optionsBoekstuk}
                    name="boekstuk"
                    id="id_boekstuk"
                    onCreateOption={createBookstuk}
                    onChange={(e) => {
                      setBoekstuk(e.value);
                    }}
                  />
                </td>
              </tr>

              <tr>
                <th>
                  <label htmlFor="id_content_ficus">Content ficus:</label>
                </th>
                <td className="field">
                  <textarea
                    onChange={(e) => setContent_ficus(e.target.value)}
                    name="content_ficus"
                    value={content_ficus}
                    cols="40"
                    rows="10"
                    maxLength="100"
                    className="input"
                    id="id_content_ficus"
                  ></textarea>
                </td>
              </tr>
            </tbody>
          </table>
        </form>
      </div>
    </div>
  );
};
export default DeclaFrom;

Thanks for your help

CodePudding user response:

I had a similar issue in a recent project. The problem you're facing is that your state is being erased when you reload the page.

In your useEffect hook, remove id from the dependency array (but leave the empty array) so that it will run once on every render. This way when you reload the page useEffect will run your api call and re-populate your state.

useEffect(() => {
    const get = async () => {
      await GET();
      const data = await GET_decla(id);
      setDecla(data);
    };
    get();
   }, []);

veel geluk!

CodePudding user response:

useState values will not persist after page reloads: this is a standard behavior of React. After page reload, all your useState values will reset to their default values.

If you need values to persist after refresh, then you will want to use a browser utility like localStorage.

As an example, this is how I would set/get the value:

const stateFromLocalStorage = localStorage.getItem("itemKey")

const [someState, setSomeState] = useState(stateFromLocalStorage || defaultState)

const settingState = (key, value) => {
  localStorage.setItem(key, value)
  setSomeState(value)
}

I grab the item from localStorage first, and attempt to assign it as the default value of the useState. If the local storage value doesn't exist, then stateFromLocalStorage will be undefined, and it will set defaultState instead because of the logical || operator.

When setting the state, I set it both with the useState setter function, as well as the local storage setItem function. That way local storage and component state will stay in sync.

  • Related