- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
提供一点背景:
我正在尝试构建一个登录表单页面功能来检测用户是否已经登录。如果他们已登录,则会出现一个按钮,提示用户注销。像这样: {user ? userLoggedInAlert() : SignIn()}
如果 user
为 True,则出现按钮,如果 user
为假,然后他们会收到用于登录身份验证的用户名和密码表单。
我已经确定了所有功能。
但是,当我按下 的按钮时注销 用户退出,我收到此错误:
×
Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.
这是我的代码,我认为
const userLoggedInAlert
有问题
import React from 'react';
import { useSelector } from 'react-redux';
import { selectUser } from '../../features/userSlice';
import SignIn from '../auth/Login';
import Container from '@material-ui/core/Container';
import { Button } from '@material-ui/core';
import { logout } from "../../features/userSlice";
import { NavLink } from 'react-router-dom';
import { useDispatch } from 'react-redux';
import LogOut from '../auth/Logout';
function LoginUser()
{
const user = useSelector(selectUser);
const dispatch = useDispatch();
const handleLogout = (e) =>
{
if(e) e.preventDefault();
dispatch(logout());
};
const userLoggedInAlert = () =>
{
return <Container>
<span>
You are already logged in!
</span>
<Button
component={NavLink}
variant="contained"
color="primary"
to="/logout"
onClick={function(){ LogOut(); handleLogout()}}
>
Do you want to logout?
</Button>
</Container>
};
return (
<Container>
{user ? userLoggedInAlert() : SignIn()}
</Container>
);
}
export default LoginUser;
SignIn()
工作得很好,我的useDispatch
也是如此,以及创建上述代码所需的其他组件。我很确定我只是弄乱了上面代码中某处的语法? LogOut()
,请注意,我可以使用完全相同的组件通过其他方式注销。
import React, { useEffect } from 'react';
import axiosInstance from '../../axios';
import { useHistory } from 'react-router-dom';
export default function LogOut() {
const history = useHistory();
useEffect(() => {
const response = axiosInstance.post('user/logout/blacklist/', {
refresh_token: localStorage.getItem('refresh_token'),
});
localStorage.removeItem('access_token');
localStorage.removeItem('refresh_token');
axiosInstance.defaults.headers['Authorization'] = null;
history.push('/login');
});
return <div>Logout</div>;
};
感谢您的帮助,我被困在这里。
"dependencies": {
"@material-ui/core": "^4.11.2",
"@material-ui/icons": "^4.11.2",
"@material-ui/lab": "^4.0.0-alpha.57",
"@reduxjs/toolkit": "^1.5.0",
"@testing-library/jest-dom": "^5.11.6",
"@testing-library/react": "^11.2.2",
"@testing-library/user-event": "^12.6.0",
"axios": "^0.21.1",
"chart.js": "^2.9.4",
"react": "^17.0.1",
"react-chartjs-2": "^2.11.1",
"react-dom": "^17.0.1",
"react-facebook-login": "^4.1.1",
"react-hook-form": "^6.14.2",
"react-redux": "^7.2.2",
"react-router-dom": "^5.2.0",
"react-scripts": "4.0.1",
"redux": "^4.0.5",
"redux-persist": "^6.0.0",
"web-vitals": "^0.2.4"
},
编辑编辑:
Uncaught Error: Objects are not valid as a React child (found: object with keys {logoutUser}). If you meant to render a collection of children, use an array instead.
上述错误发生在
<useLogOut>
零件。
LoginPortal.js
import React from 'react';
import { useSelector } from 'react-redux';
import { selectUser } from '../../features/userSlice';
import SignIn from '../auth/Login';
import Container from '@material-ui/core/Container';
import { Button } from '@material-ui/core';
import { logout } from "../../features/userSlice";
import { NavLink } from 'react-router-dom';
import { useDispatch } from 'react-redux';
import useLogOut from '../auth/Logout';
function LoginUser()
{
const user = useSelector(selectUser);
// use hook at component body extracting logoutUser method
const { logoutUser } = useLogOut();
const dispatch = useDispatch();
const handleLogout = (e) =>
{
if(e) e.preventDefault();
dispatch(logout());
};
const UserLoggedInAlert = () =>
{
return <Container>
<span>
You are already logged in!
</span>
<Button
component={NavLink}
variant="contained"
color="primary"
to="/logout"
// here now you can save logout user since no hooks are being called
onClick={function(){ logoutUser(); handleLogout()}}
>
Do you want to logout?
</Button>
</Container>
};
return (
<Container>
{user ? <UserLoggedInAlert/> : <SignIn/> }
</Container>
);
}
export default LoginUser;
Logout.js
零件:
import axiosInstance from '../../axios';
import { useHistory } from 'react-router-dom';
export default function useLogOut() {
const history = useHistory();
// we don't useEffect here, we are only interested in function logoutUser
const logoutUser = () => {
const response = axiosInstance.post('user/logout/blacklist/', {
refresh_token: localStorage.getItem('refresh_token'),
});
localStorage.removeItem('access_token');
localStorage.removeItem('refresh_token');
axiosInstance.defaults.headers['Authorization'] = null;
history.push('/login');
}
return { logoutUser }
};
我的 index.js:
import useLogOut from './components/auth/Logout';
const routing = (
<Router>
<Route path="/logout" component={useLogOut} />
</Router>
);
ReactDOM.render(routing, document.getElementById('root'));
既然我已经改变了它,这将是我的索引路由器的正确路径吗?
Error: Objects are not valid as a React child (found: object with keys {logoutUser}). If you meant to render a collection of children, use an array instead.
最佳答案
当您调用 Logout
在 onClick
你正在从你的函数中调用钩子(Hook) Logout
在组件主体之外,什么是不允许的。
您可以将 Logout 逻辑抽象为自定义 Hook ,在该 Hook 中返回 logoutUser
功能:
export default function useLogOut() {
const history = useHistory();
// we don't useEffect here, we are only interested in function logoutUser
const logoutUser = () => {
const response = axiosInstance.post('user/logout/blacklist/', {
refresh_token: localStorage.getItem('refresh_token'),
});
localStorage.removeItem('access_token');
localStorage.removeItem('refresh_token');
axiosInstance.defaults.headers['Authorization'] = null;
history.push('/login');
}
return { logoutUser }
};
然后你在你的
LoginUser
使用你的自定义钩子(Hook)组件主体,提取
logoutUser
方法:
function LoginUser()
{
const user = useSelector(selectUser);
// use hook at component body extracting logoutUser method
const { logoutUser } = useLogOut();
const dispatch = useDispatch();
const handleLogout = (e) =>
{
if(e) e.preventDefault();
dispatch(logout());
};
const UserLoggedInAlert = () =>
{
return <Container>
<span>
You are already logged in!
</span>
<Button
component={NavLink}
variant="contained"
color="primary"
to="/logout"
// here now you can safely logout user since no hooks are being called
onClick={function(){ handleLogout(); logoutUser()}}
>
Do you want to logout?
</Button>
</Container>
};
return (
<Container>
{user ? <UserLoggedInAlert/> : <SignIn/> }
</Container>
);
}
export default LoginUser;
您可以领先一步,简化您的
LogOut
零件:
export default function LogOut() {
const { logoutUser } = useLogOut();
useEffect(() => {
logoutUser()
});
return <div>Logout</div>;
};
编辑
export const useLogOut = () => {
const history = useHistory();
// we don't useEffect here, we are only interested in function logoutUser
const logoutUser = () => {
const response = axiosInstance.post('user/logout/blacklist/', {
refresh_token: localStorage.getItem('refresh_token'),
});
localStorage.removeItem('access_token');
localStorage.removeItem('refresh_token');
axiosInstance.defaults.headers['Authorization'] = null;
history.push('/login');
}
return { logoutUser }
};
export default function LogOut() {
const { logoutUser } = useLogOut();
useEffect(() => {
logoutUser()
});
return <div>Logout</div>;
};
在您的登录处,您使用大括号导入钩子(Hook):
import { useLogOut } from '../auth/Logout';
并在没有大括号的 index.js 处导入组件:
import LogOut from './components/auth/Logout';
const routing = (
<Router>
<Route path="/logout" component={LogOut} />
</Router>
);
关于javascript - React - 错误 : Invalid hook call. Hooks 只能在函数组件的主体内部调用。我的语法有什么问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66056529/
C语言sscanf()函数:从字符串中读取指定格式的数据 头文件: ?
最近,我有一个关于工作预评估的问题,即使查询了每个功能的工作原理,我也不知道如何解决。这是一个伪代码。 下面是一个名为foo()的函数,该函数将被传递一个值并返回一个值。如果将以下值传递给foo函数,
CStr 函数 返回表达式,该表达式已被转换为 String 子类型的 Variant。 CStr(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CSng 函数 返回表达式,该表达式已被转换为 Single 子类型的 Variant。 CSng(expression) expression 参数是任意有效的表达式。 说明 通常,可
CreateObject 函数 创建并返回对 Automation 对象的引用。 CreateObject(servername.typename [, location]) 参数 serv
Cos 函数 返回某个角的余弦值。 Cos(number) number 参数可以是任何将某个角表示为弧度的有效数值表达式。 说明 Cos 函数取某个角并返回直角三角形两边的比值。此比值是
CLng 函数 返回表达式,此表达式已被转换为 Long 子类型的 Variant。 CLng(expression) expression 参数是任意有效的表达式。 说明 通常,您可以使
CInt 函数 返回表达式,此表达式已被转换为 Integer 子类型的 Variant。 CInt(expression) expression 参数是任意有效的表达式。 说明 通常,可
Chr 函数 返回与指定的 ANSI 字符代码相对应的字符。 Chr(charcode) charcode 参数是可以标识字符的数字。 说明 从 0 到 31 的数字表示标准的不可打印的
CDbl 函数 返回表达式,此表达式已被转换为 Double 子类型的 Variant。 CDbl(expression) expression 参数是任意有效的表达式。 说明 通常,您可
CDate 函数 返回表达式,此表达式已被转换为 Date 子类型的 Variant。 CDate(date) date 参数是任意有效的日期表达式。 说明 IsDate 函数用于判断 d
CCur 函数 返回表达式,此表达式已被转换为 Currency 子类型的 Variant。 CCur(expression) expression 参数是任意有效的表达式。 说明 通常,
CByte 函数 返回表达式,此表达式已被转换为 Byte 子类型的 Variant。 CByte(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CBool 函数 返回表达式,此表达式已转换为 Boolean 子类型的 Variant。 CBool(expression) expression 是任意有效的表达式。 说明 如果 ex
Atn 函数 返回数值的反正切值。 Atn(number) number 参数可以是任意有效的数值表达式。 说明 Atn 函数计算直角三角形两个边的比值 (number) 并返回对应角的弧
Asc 函数 返回与字符串的第一个字母对应的 ANSI 字符代码。 Asc(string) string 参数是任意有效的字符串表达式。如果 string 参数未包含字符,则将发生运行时错误。
Array 函数 返回包含数组的 Variant。 Array(arglist) arglist 参数是赋给包含在 Variant 中的数组元素的值的列表(用逗号分隔)。如果没有指定此参数,则
Abs 函数 返回数字的绝对值。 Abs(number) number 参数可以是任意有效的数值表达式。如果 number 包含 Null,则返回 Null;如果是未初始化变量,则返回 0。
FormatPercent 函数 返回表达式,此表达式已被格式化为尾随有 % 符号的百分比(乘以 100 )。 FormatPercent(expression[,NumDigitsAfterD
FormatNumber 函数 返回表达式,此表达式已被格式化为数值。 FormatNumber( expression [,NumDigitsAfterDecimal [,Inc
我是一名优秀的程序员,十分优秀!