我有一个包含登录表单的导航栏。
通过用户名、密码和 ID 进行识别。
如果用户已经连接到系统,将出现一个注销表单。
检查用户是否连接,使用 userContext 完成。
我有一个“submitHandler”函数,它确实获取到 DB A,以查看用户是否已在系统中注册。
然后我有一个“getUserType”函数,它确实获取到 DB B,以查看用户的类型是什么。
(我没有选择将 2 fetch 合并为一个调用,这将返回用户是否已注册,以及他的类型是什么......)
在第一次单击提交按钮时 - 一切正常。如果我输入了不正确的数据,我可以看到微调器并收到错误消息。
如果我再次单击提交按钮,根据调试器,第一次 fetch 调用返回错误:“无法在未安装的组件上执行 React 状态更新。这是一个空操作,但它表明内存泄漏您的应用程序。要修复,请取消 useEffect 清理函数中的所有订阅和异步任务。”
而且我的整个屏幕都被擦除了,我只看到一个白色的屏幕。
我究竟做错了什么?如何解决?它与useEffect有关吗?
我很高兴得到你的帮助。谢谢!
const Test = (props) => {
const [userLoginDetails, setUserLoginDetails] = useState({
userName: "",
userPassword: "",
userID: "",
});
const [isLoading, setIsLoading] = useState(false);
const [isLogIn, setIsLogin] = useState(false);
const [isCompanyMember, setIsCompanyMember] = useState(false);
const [error, setError] = useState(false);
const [message, setMessage] = useState("");
const userContext = useContext(UserContext);
const userAuth = userContext.authed;
const onChangeHandler = (e) => {
let { name, value } = e.target;
let updatedState = { ...userLoginDetails };
updatedState[name] = value;
setUserLoginDetails(updatedState);
};
const getUserType = async () => {
const bodyContent = {
userName: userLoginDetails.userName,
};
const response = await fetch(`${URL}/members/${userLoginDetails.userID}`, {
method: "post",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(bodyContent),
credentials: "include",
});
if (!response.ok) {
setError(true);
setIsLoading(false);
setMessage("something went wrong! try again!");
return;
}
const body = await response.json();
userContext.handleChange(body.data.result, true, userLoginDetails.userName);
setIsLogin(true);
setError(false);
setIsLoading(false);
setMessage("");
};
const submitHandler = async (e) => {
e.preventDefault();
setIsLoading(true);
setError(false);
fetch(`someURL`, {
method: "post",
json: true,
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
UserName: userLoginDetails.userName,
PassWord: userLoginDetails.userPassword,
Id: userLoginDetails.userID,
}),
})
.then((response) => {
return response.json();
})
.then((response) => {
//The combination of user, id and password is correct!
if (response) {
setIsCompanyMember(true);
} else {
//The combination of user, id and password is wrong!
setError(true);
setIsLoading(false);
setMessage("combination of user,id an password didnt work!");
}
})
//unexpected problem...
.catch(() => {
setError(true);
setIsLoading(false);
setMessage("connection problem");
});
};
useEffect(() => {
fetch(`${URL}/login/`, { credentials: "include" })
.then((response) => {
return response.json();
})
.then((response) => {
console.log(response);
if (response.data.loggedIn === true) {
setIsLogin(true);
setError(false);
setMessage("");
userContext.handleChange(
response.data.userType,
true,
response.data.userName
);
}
})
.catch();
return () => {
//for cleanup
};
}, []);
useEffect(() => {
if (isCompanyMember) {
getUserType();
}
}, [isCompanyMember]);
return (
<nav>
{/* An alert message */}
{!isLogIn && error && (
<div role="alert" style={{ margin: "auto" }}>
{message}
<button
type="button"
className="close"
data-dismiss="alert"
aria-label="Close"
>
<span aria-hidden="true">×</span>
</button>
</div>
)}
{/* login and logout forms */}
<ul>
<li>
{isLoading && <TinySpinner />}
{!userAuth && (
<form id={classes.login} onSubmit={submitHandler}>
<div>
<input
type="text"
name="userName"
id={classes.login_username}
placeholder="Username"
autoComplete="username"
onChange={onChangeHandler}
value={userLoginDetails.userName}
></input>
</div>
<div>
<input
type="password"
name="userPassword"
id={classes.login_password}
placeholder="Password"
autoComplete="current-password"
onChange={onChangeHandler}
value={userLoginDetails.userPassword}
></input>
</div>
<div>
<input
type="text"
name="userID"
id={classes.login_userid}
placeholder="ID"
autoComplete="id"
onChange={onChangeHandler}
value={userLoginDetails.userID}
></input>
</div>
<div>
<input type="submit" value="Log in"></input>
</div>
</form>
)}
{/* TODO: logout form */}
</li>
</ul>
</nav>
);
};
export default Test;