#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, оно несколько раз выдает пустую строку. поскольку данные не отправляются, а сервер выдает ошибку 4222. @adityakumar Не отправляйте запрос, если значение тогда пустое. Разве это невозможно?
3. невозможно, чтобы весь контент отображался на экране со стороны сервера.
4. @adityakumar Можете ли вы отправить CodeSandbox.io песочница, чтобы мы могли заставить ее работать? У вас это работает?