【发布时间】:2021-12-09 21:26:48
【问题描述】:
我尝试使用 localStorage 保存输入的值,但我遇到了一个奇怪的错误,它不会从 localStorage 加载数据。
1-我在InputFile.js的useEffect中用setItem设置了多个输入的数据
useEffect(() => {
let validateInputs = {
fullNameValidate: enteredFullNameIsValid,
phoneValidate: enteredPhoneIsValid,
};
setValidation(validateInputs);
const allData = { fullNameEntered, phoneEntered };
localStorage.setItem("data", JSON.stringify(allData));
}, [
enteredFullNameIsValid,
enteredPhoneIsValid,
setValidation,
fullNameEntered,
phoneEntered,
]);
2 - 我在自定义钩子(use-input.js)中更新处理程序的值:
const [enteredValue, setEnteredValue] = useState({
enterValidate: "",
});
const valueChangeHandler = (event) => {
setEnteredValue({
...enteredValue,
enterValidate: event.target.value,
});
};
3- 我尝试使用保存的值(在自定义挂钩中,use-input.js):
useEffect(() => {
const saved = localStorage.getItem("data");
const { fullNameEntered, phoneEntered } = JSON.parse(saved);
setEnteredValue((prevState) => {
return { ...prevState, fullNameEntered, phoneEntered };
});
}, []);
但它不起作用!
更新:
这里有两个完整的文件:
1- 输入的自定义钩子
const useInput = (validateValue) => {
const [enteredValue, setEnteredValue] = useState({
enterValidate: "",
});
const [isTouched, setIsTouched] = useState(false);
const [clickClasses, setClickClasses] = useState(false);
const valueIsValid = validateValue(enteredValue.enterValidate);
const hasError = !valueIsValid && isTouched;
const valueChangeHandler = (event) => {
setEnteredValue({
...enteredValue,
enterValidate: event.target.value,
});
};
const inputBlurHandler = () => {
setIsTouched(true);
setClickClasses(false);
};
const inputClickHandler = () => {
setClickClasses(!clickClasses);
};
const reset = () => {
setEnteredValue("");
setIsTouched(false);
};
////TAKE STORED DATA////// BUT IT DOESN'T WORK
useEffect(() => {
const saved = localStorage.getItem("data");
const { fullNameEntered, phoneEntered } = JSON.parse(saved);
setEnteredValue((prevState) => {
return { ...prevState, fullNameEntered, phoneEntered };
});
}, []);
console.log(enteredValue);
return {
value: enteredValue.enterValidate,
isValid: valueIsValid,
hasError,
valueChangeHandler,
inputBlurHandler,
inputClickHandler,
click: clickClasses,
reset,
};
};
export default useInput;
2- 输入文件
import React, { useEffect } from "react";
import useInput from "../../../../../hooks/use-input";
import validateInput from "../../../../../utils/validateInput";
import {
WrapperNamePhone,
LabelNamePhone,
SpanInputDescription,
InputStyle,
} from "../ContactFormInput.style";
export default function FullNamePhoneInput({ setValidation }) {
//FullName Input
const {
value: fullNameEntered,
isValid: enteredFullNameIsValid,
hasError: fullNameHasError,
valueChangeHandler: fullNameChangeHandler,
inputBlurHandler: fullNameBlurHandler,
inputClickHandler: fullNameClickHandler,
click: fullNameClickClasses,
} = useInput((value) => {
const inputValidFullName = {
value: value,
maxLength: 20,
whiteSpace: true,
allowNumber: false,
allowStrings: true,
};
return validateInput(inputValidFullName);
});
//Phone numbers input
const {
value: phoneEntered,
isValid: enteredPhoneIsValid,
hasError: phoneHasError,
valueChangeHandler: phoneChangeHandler,
inputBlurHandler: phoneBlurHandler,
} = useInput((value) => {
const inputValidPhone = {
value: value,
maxLength: 15,
whiteSpace: true,
allowNumber: true,
allowStrings: false,
};
return validateInput(inputValidPhone);
});
useEffect(() => {
let validateInputs = {
fullNameValidate: enteredFullNameIsValid,
phoneValidate: enteredPhoneIsValid,
};
setValidation(validateInputs);
//STORE DATA////
const allData = { fullNameEntered, phoneEntered };
localStorage.setItem("data", JSON.stringify(allData));
}, [
enteredFullNameIsValid,
enteredPhoneIsValid,
setValidation,
fullNameEntered,
phoneEntered,
]);
//FUll NAME
const borderColorFullName = fullNameHasError ? `rgb(245, 2, 2)` : `#d5d9dc`;
const clickedColor = fullNameClickClasses ? "#2696e8" : "#a4aeb4";
//PHONE NUMBERS
const borderColorPhone = phoneHasError ? `rgb(245, 2, 2)` : `#d5d9dc`;
return (
<WrapperNamePhone>
<LabelNamePhone htmlFor="full-name">
<SpanInputDescription clickedColor={clickedColor}>
Full name
</SpanInputDescription>
<InputStyle
type="text"
name="full-name"
id="full-name"
borderColor={borderColorFullName}
value={fullNameEntered}
onChange={fullNameChangeHandler}
onBlur={fullNameBlurHandler}
onClick={fullNameClickHandler}
/>
{fullNameHasError && <p> - Enter a valid Full Name</p>}
</LabelNamePhone>
<LabelNamePhone htmlFor="phoneNumber">
<InputStyle
placeholder="Enter a valid phone number"
type="text"
name="phoneNumber"
borderColor={borderColorPhone}
value={phoneEntered}
onChange={phoneChangeHandler}
onBlur={phoneBlurHandler}
/>
{phoneHasError && <p> - Enter a valid Phone Number</p>}
</LabelNamePhone>
</WrapperNamePhone>
);
}
/////////////////////// ///////////////////////
最终更新,我不喜欢这个解决方案,但它有效! 我已经这样做了:
-1 我从输入文件中删除了 setKeys。
-2 我在 use-input 钩子中动态更新 setKeys:
-3 然后使用 useState 我更新 getItem!
const [enteredValue, setEnteredValue] = useState(() => {
return {
validateInput: "",
fullName: JSON.parse(localStorage.getItem("fullName")) || "",
phoneNumber: JSON.parse(localStorage.getItem("phoneNumber")) || "",
email: JSON.parse(localStorage.getItem("email")) || "",
country: JSON.parse(localStorage.getItem("country")) || "",
From: JSON.parse(localStorage.getItem("From")) || "",
To: JSON.parse(localStorage.getItem("To")) || "",
};
});
const valueChangeHandler = (event) => {
setEnteredValue({
[event.target.name]: event.target.value,
validateInput: event.target.value,
});
localStorage.setItem(event.target.name, JSON.stringify(event.target.value));
};
*/ Other code for validation, useless in this example */
return {
value: enteredValue.validateInput,
valueName: enteredValue.fullName,
valuePhone: enteredValue.phoneNumber,
valueEmail: enteredValue.email,
valueCountry: enteredValue.country,
valueFrom: enteredValue.From,
valueTo: enteredValue.To,
isValid: valueIsValid,
hasError,
valueChangeHandler,
inputBlurHandler,
inputClickHandler,
click: clickClasses,
reset,
};
【问题讨论】:
-
我不确定我是否理解; “setEnteredValue”不区分姓名/电话,也不清楚您如何将更新存储回本地存储。并且初始状态值将始终按照显示的顺序进行。您可能需要提供更多详细信息。
-
我已经更新了帖子,现在我想我的意思更清楚了,谢谢
标签: reactjs local-storage