Как сохранить выбор данных при обновлении страницы в react js

#javascript #reactjs

#javascript #reactjs

Вопрос:

Я создаю, где у него мало выпадающих списков. Здесь проблема заключается в том, когда пользователь делает выбор в выпадающем списке, и если они обновляют значение выбора выпадающего списка, сбрасывается обратно к значению по умолчанию. Вместо этого я хочу, чтобы значение сохранялось, чтобы при обновлении пользователем оно получало значение из последнего выбранного выпадающего списка.

Для этого я попытался использовать localstorage, и он сохраняет значение. Но внутри useEffect я пытаюсь получить значение и передать его для вызова api, он несколько раз выдает пустую строку. Поскольку сервер выдает мне ошибку.

Вот мой код

 const DispensingIncidents = (props) => {
  const classes = useStyles();
  const {
    getFilterData,
    dispensingData, // data from server side
    getOverviewData,
    location,
    history,
    getAnalysis,
    clearAnalysis,
    getDuration,
  } = props;

  const [timeSpan, setTimeSpan] = React.useState("");
  const [year, setYear] = React.useState(2020);
  const [tabValue, setTabValue] = React.useState(0);
  const [spanData, setSpanData] = React.useState([]);
  const [dataType, setDataType] = React.useState("");
  const [durationLabel, setDurationLabel] = React.useState("");
  const [dataTo, setDataTo] = React.useState("");
  const [dataFrom, setDataFrom] = React.useState("");
  // incidencesSection hide and show
  const [incidencesSection, setIncidencesSection] = React.useState(false);
  // handle overview select state
  const [overViewSelect, setOverViewSelect] = React.useState("");
  // stay selected tab on refresh
  // eslint-disable-next-line
  const [selectTab, setSelectTab] = React.useState(0);

  const {
    loading,
    duration,
    period,
    type,
    _reference,
    dispensingOverviewData,
    overviewDataLoading,
    incidenceAnalysisData, // bottom accordion data,
    incidenceAnalysisDataArray, // bottom accordion data array
    analysisDataLoading,
  } = dispensingData;

  const { count } = dispensingOverviewData;

  useEffect(() => {
    history.replace({
      pathname: location.pathname,
      search: `?year=${year}amp;period=${timeSpan}amp;type=${dataType}amp;duration=${durationLabel}amp;overview=${overViewSelect}`,
    });
    setYear(year);
    setTimeSpan(timeSpan);
    window.localStorage.setItem(
      "incidenceState",
      JSON.stringify({
        year,
        timeSpan,
        dataType,
        durationLabel,
        dataTo,
        dataFrom,
      })
    );
    return () => {
      window.localStorage.removeItem("incidenceState");
    };
    // eslint-disable-next-line
  }, [
    year,
    timeSpan,
    dataType,
    durationLabel,
    overViewSelect,
    dataTo,
    dataFrom,
  ]);

  /**
   *  This updates on Year given
   */
  useEffect(() => {
    getFilterData(year);
    getDuration(year);
  }, [getFilterData, year, getDuration]);
  const [once, setOnce] = React.useState(0);
  useEffect(() => {
    if (duration !== "" amp;amp; type !== "") {
      if (
        type !== "" amp;amp;
        once === 0 amp;amp;
        duration.monthly.length > 0 amp;amp;
        _reference !== ""
      ) {
        setOnce(1);
        console.log("OverviewPeriod", Object.keys(period));
        getOverviewData(
          Object.keys(period)[3],
          duration.monthly[0].period.to,
          duration.monthly[0].period.from,
          Object.keys(type)[0],
          _reference
        );

        setTimeSpan(Object.keys(period)[3]);
        setDataFrom(duration.monthly[0].period.from);
        setDataTo(duration.monthly[0].period.to);
        setDataType(Object.keys(type)[0]);
      }
    }
  }, [duration, type]);

  /**
   * GET query from url search param
   *  @usage query.get("year")
   */
  function useQuery() {
    return new URLSearchParams(location.search);
  }
  const query = useQuery();
  const time = query.get("period");
  useEffect(() => {
    if (time === "yearly") {
      const yearlyData = duration["yearly"];
      setSpanData(yearlyData);
    } else if (time === "weekly") {
      const weeklyData = duration["weekly"];
      setSpanData(weeklyData);
    } else if (time === "quarterly") {
      const quarterlyData = duration["quarterly"];
      setSpanData(quarterlyData);
    } else if (time === "monthly") {
      const monthlyData = duration["monthly"];
      setSpanData(monthlyData);
    } else if (time === "6 months") {
      const halfYearlyData = duration["half-yearly"];
      setSpanData(halfYearlyData);
    }
  }, [time, duration]);

  /**
   *
   * @param {*} event
   * @param {*} newValue
   * on tab change
   */

  // eslint-disable-next-line
  const handleTabChange = (event, newValue) => {
    setTabValue(newValue);
  };
  useEffect(() => {
    if (duration !== "") {
      getOverviewData(
        timeSpan,
        duration.monthly[0].period.to,
        duration.monthly[0].period.from,
        dataType,
        _reference
      );
    }
  }, [duration]);

  /**
   * Year change
   * @param {*} event
   */
  const handleYearChange = (event) => {
    const v = event.target.value;
    setYear(v);
    setTimeSpan(query.get("period"));
    getDuration(v);
  };

  /**
   * Span change
   * @param {*} event
   */
  const handleSpanChange = (event) => {
    const value = event.target.value;

    const reValue = value === "6 months" ? "half-yearly" : value;
    setTimeSpan(value);

    getOverviewData(
      value,
      duration[reValue][0].period.to,
      duration[reValue][0].period.from,
      dataType,
      _reference
    );
    setDataTo(duration[reValue][0].period.to);
    setDataFrom(duration[reValue][0].period.from);
    setIncidencesSection(false);
    setOverViewSelect("");
  };

  const handleSpanTabChange = (data, i) => {
    setSelectTab(i);
    setDataTo(data.period.to);
    setDataFrom(data.period.from);
    getOverviewData(
      time,
      data.period.to,
      data.period.from,
      dataType,
      _reference
    );
    setDurationLabel(data.label);
    setOverViewSelect("");
    setIncidencesSection(false);
  };
  const handleDataTypeChange = (event) => {
    setDataType(event.target.value);
    getOverviewData(time, dataTo, dataFrom, event.target.value, _reference);
    setIncidencesSection(false);
    setOverViewSelect("");
  };

  const handleOverViewClick = (data) => {
    clearAnalysis();
    setOverViewSelect(data);
    const value = time === "6 months" ? "half_yearly" : time;
    getAnalysis(data, value, dataFrom, dataTo, dataType, 1, _reference);
    setIncidencesSection(true);
  };

  const handlePageNext = (pageNo) => {
    getAnalysis(
      overViewSelect,
      time,
      dataFrom,
      dataTo,
      dataType,
      pageNo,
      _reference
    );
  };
  // useEffect(() => {
  //   const localValue = JSON.parse(
  //     window.localStorage.getItem("incidenceState")
  //   );

  //   console.log("localValue", localValue);
  // }, []);

  return (
    <div className={classes.dispenseRoot}>
      <Paper
        elementType="div"
        elevation={5}
        square={true}
        variant="elevation"
        className={classes.topContainer}
      >
        <div className={classes.topContainerDiv}>
          <div className={classes.topContainerLeft}>
            <div className={classes.headerTextDiv}>
              <p>Period</p>
            </div>
            <FormControl variant="outlined" className={classes.formControl}>
              <Select
                className={classes.containerSelect}
                id="demo-simple-select-outlined"
                value={timeSpan}
                onChange={handleSpanChange}
              >
                {Object.values(period).map((span, i) => {
                  return (
                    <MenuItem key={i} value={span.toLowerCase()}>
                      {span.toUpperCase()}
                    </MenuItem>
                  );
                })}
              </Select>
            </FormControl>
            <FormControl variant="outlined" className={classes.formControl}>
              <Select
                className={classes.containerSelect}
                id="demo-simple-select-outlined"
                value={year}
                onChange={handleYearChange}
              >
                <MenuItem value={2020}>2020</MenuItem>
                <MenuItem value={2019}>2019</MenuItem>
                <MenuItem value={2018}>2018</MenuItem>
                <MenuItem value={2017}>2017</MenuItem>
              </Select>
            </FormControl>
            <div className={classes.typeHeading}>
              <p>Type</p>
            </div>
            <FormControl variant="outlined" className={classes.formControl}>
              <Select
                className={classes.containerSelect}
                id="demo-simple-select-outlined"
                value={dataType}
                onChange={handleDataTypeChange}
              >
                {Object.keys(type).map((key) => {
                  return (
                    <MenuItem key={key} value={key}>
                      {key.toUpperCase()}
                    </MenuItem>
                  );
                })}
              </Select>
            </FormControl>
            
          </div>
         
        </div>
      </Paper>
      <div className={classes.dispensingIncidentsTabDiv}>
        <Paper square>
          <Tabs
            value={tabValue}
            indicatorColor="primary"
            textColor="primary"
            onChange={handleTabChange}
            variant="scrollable"
            scrollButtons="on"
            aria-label="scrollable auto tabs example"
          >
            <Tab
              className={classes.dispensingTab}
              label="INCIDENCES"
              {...a11yProps(0)}
            />
          
          </Tabs>
        </Paper>
                  </div>
      {incidencesSection ? (
        <div className={classes.incidencesAccordionDiv}>
          <IncidenceAccordion
            handlePageNext={handlePageNext}
            incidenceAnalysisDataArray={incidenceAnalysisDataArray}
            data={incidenceAnalysisData}
            title={"Incidences"}
          />
        </div>
      ) : null}
    </div>
  );
};
 

Ответ №1:

Каждый раз, когда вы вызываете setX() useState() hook, попробуйте сохранить значение в localStorage . Короче говоря, я бы сделал:

 const [Value, setValue] = useState("");
const handleSetValue = (newValue) => {
  setValue(newValue);
  window.localStorage.setItem("Value", newValue);
}
 

И я использую handleSetValue() вместо setValue . И точно так же, в useEffect() хук, я попытаюсь загрузить все значения таким образом:

 useEffect(() => {
  // While loading, load the state from the localStorage.
  if (window.localStorage.getItem("Value"))
    setValue(window.localStorage.getItem("Value"));
}, [])
 

Приведенный выше код поможет вам сохранить ваши данные при перезагрузках.

Комментарии:

1. Я сделал примерно то же самое. Здесь моя проблема заключается в том, что при монтировании компонента компонента я также делаю сетевой запрос со значением, которое я получаю, if value is in localStorage then from localStorage else the default value specified но когда я пытаюсь получить значение из localstorage в useEffect, оно несколько раз выдает пустую строку. поскольку данные не отправляются, а сервер выдает ошибку 422

2. @adityakumar Не отправляйте запрос, если значение тогда пустое. Разве это невозможно?

3. невозможно, чтобы весь контент отображался на экране со стороны сервера.

4. @adityakumar Можете ли вы отправить CodeSandbox.io песочница, чтобы мы могли заставить ее работать? У вас это работает?