我正在使用Django rest framework(Djoser)构建一个react应用程序以进行认证。现在我使用react redx来管理身份验证。bt在使用connect方法传递stattoprops时不知何故得到此错误。而不是错误的确切位置。
以下是我的档案:减速器Atyh文件:
import {
LOGIN_SUCCESS,
LOGIN_FAIL,
USER_LOADED_SUCCESS,
USER_LOADED_FAIL,
AUTHENTICATED_SUCCESS,
AUTHENTICATED_FAIL,
PASSWORD_RESET_SUCCESS,
PASSWORD_RESET_FAIL,
PASSWORD_RESET_CONFIRM_SUCCESS,
PASSWORD_RESET_CONFIRM_FAIL,
SIGNUP_SUCCESS,
SIGNUP_FAIL,
ACTIVATION_SUCCESS,
ACTIVATION_FAIL,
GOOGLE_AUTH_SUCCESS,
GOOGLE_AUTH_FAIL,
FACEBOOK_AUTH_SUCCESS,
FACEBOOK_AUTH_FAIL,
LOGOUT
} from '../Actions/Types';
const initialState = {
access: localStorage.getItem('access'),
refresh: localStorage.getItem('refresh'),
isAuthenticated: false,
user: null
};
export default function(state = initialState, action) {
const { type, payload } = action;
switch(type) {
case AUTHENTICATED_SUCCESS:
return {
...state,
isAuthenticated: true
}
case LOGIN_SUCCESS:
case GOOGLE_AUTH_SUCCESS:
case FACEBOOK_AUTH_SUCCESS:
localStorage.setItem('access', payload.access);
localStorage.setItem('refresh', payload.refresh);
return {
...state,
isAuthenticated: true,
access: payload.access,
refresh: payload.refresh
}
case SIGNUP_SUCCESS:
return {
...state,
isAuthenticated: false
}
case USER_LOADED_SUCCESS:
return {
...state,
user: payload
}
case AUTHENTICATED_FAIL:
return {
...state,
isAuthenticated: false
}
case USER_LOADED_FAIL:
return {
...state,
user: null,
}
case GOOGLE_AUTH_FAIL:
case FACEBOOK_AUTH_FAIL:
case LOGIN_FAIL:
case SIGNUP_FAIL:
case LOGOUT:
localStorage.removeItem('access');
localStorage.removeItem('refresh');
return {
...state,
access: null,
refresh: null,
isAuthenticated: false,
user: null,
error:payload.detail
}
case PASSWORD_RESET_SUCCESS:
case PASSWORD_RESET_FAIL:
case PASSWORD_RESET_CONFIRM_SUCCESS:
case PASSWORD_RESET_CONFIRM_FAIL:
case ACTIVATION_SUCCESS:
case ACTIVATION_FAIL:
return {
...state
}
default:
return state
}}
操作身份验证文件:
import axios from 'axios';
import {
LOGIN_SUCCESS,
LOGIN_FAIL,
USER_LOADED_SUCCESS,
USER_LOADED_FAIL,
AUTHENTICATED_SUCCESS,
AUTHENTICATED_FAIL,
PASSWORD_RESET_SUCCESS,
PASSWORD_RESET_FAIL,
PASSWORD_RESET_CONFIRM_SUCCESS,
PASSWORD_RESET_CONFIRM_FAIL,
SIGNUP_SUCCESS,
SIGNUP_FAIL,
ACTIVATION_SUCCESS,
ACTIVATION_FAIL,
GOOGLE_AUTH_SUCCESS,
GOOGLE_AUTH_FAIL,
FACEBOOK_AUTH_SUCCESS,
FACEBOOK_AUTH_FAIL,
LOGOUT
} from './Types';
export const load_user = () => async dispatch => {
if (localStorage.getItem('access')) {
const config = {
headers: {
'Content-Type': 'application/json',
'Authorization': `JWT ${localStorage.getItem('access')}`,
'Accept': 'application/json'
}
};
try {
const res = await axios.get(`${process.env.REACT_APP_API_URL}/auth/users/me/`, config);
dispatch({
type: USER_LOADED_SUCCESS,
payload: res.data
});
} catch (err) {
dispatch({
type: USER_LOADED_FAIL
});
}
} else {
dispatch({
type: USER_LOADED_FAIL
});
}
};
export const googleAuthenticate = (state, code) => async dispatch => {
if (state && code && !localStorage.getItem('access')) {
const config = {
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
};
const details = {
'state': state,
'code': code
};
const formBody = Object.keys(details).map(key => encodeURIComponent(key) + '=' + encodeURIComponent(details[key])).join('&');
try {
const res = await axios.post(`${process.env.REACT_APP_API_URL}/auth/o/google-oauth2/?${formBody}`, config);
dispatch({
type: GOOGLE_AUTH_SUCCESS,
payload: res.data
});
dispatch(load_user());
} catch (err) {
dispatch({
type: GOOGLE_AUTH_FAIL
});
}
}
};
export const checkAuthenticated = () => async dispatch => {
if (localStorage.getItem('access')) {
const config = {
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
}
};
const body = JSON.stringify({ token: localStorage.getItem('access') });
try {
const res = await axios.post(`${process.env.REACT_APP_API_URL}/auth/jwt/verify/`, body, config)
if (res.data.code !== 'token_not_valid') {
dispatch({
type: AUTHENTICATED_SUCCESS
});
} else {
dispatch({
type: AUTHENTICATED_FAIL
});
}
} catch (err) {
dispatch({
type: AUTHENTICATED_FAIL
});
}
} else {
dispatch({
type: AUTHENTICATED_FAIL
});
}
};
export const login = (email, password) => async dispatch => {
const config = {
headers: {
'Content-Type': 'application/json'
}
};
const body = JSON.stringify({ email, password });
try {
const res = await axios.post(`${process.env.REACT_APP_API_URL}/auth/jwt/create/`, body, config);
dispatch({
type: LOGIN_SUCCESS,
payload: res.data
});
dispatch(load_user());
} catch (err) {
dispatch({
type: LOGIN_FAIL
})
}
};
export const signup = (first_name, last_name, email, password, re_password) => async dispatch => {
const config = {
headers: {
'Content-Type': 'application/json'
}
};
const body = JSON.stringify({ first_name, last_name, email, password, re_password });
try {
const res = await axios.post(`${process.env.REACT_APP_API_URL}/auth/users/`, body, config);
dispatch({
type: SIGNUP_SUCCESS,
payload: res.data
});
} catch (err) {
dispatch({
type: SIGNUP_FAIL
})
}
};
export const verify = (uid, token) => async dispatch => {
const config = {
headers: {
'Content-Type': 'application/json'
}
};
const body = JSON.stringify({ uid, token });
try {
await axios.post(`${process.env.REACT_APP_API_URL}/auth/users/activation/`, body, config);
dispatch({
type: ACTIVATION_SUCCESS,
});
} catch (err) {
dispatch({
type: ACTIVATION_FAIL
})
}
};
export const reset_password = (email) => async dispatch => {
const config = {
headers: {
'Content-Type': 'application/json'
}
};
const body = JSON.stringify({ email });
try {
await axios.post(`${process.env.REACT_APP_API_URL}/auth/users/reset_password/`, body, config);
dispatch({
type: PASSWORD_RESET_SUCCESS
});
} catch (err) {
dispatch({
type: PASSWORD_RESET_FAIL
});
}
};
export const reset_password_confirm = (uid, token, new_password, re_new_password) => async dispatch => {
const config = {
headers: {
'Content-Type': 'application/json'
}
};
const body = JSON.stringify({ uid, token, new_password, re_new_password });
try {
await axios.post(`${process.env.REACT_APP_API_URL}/auth/users/reset_password_confirm/`, body, config);
dispatch({
type: PASSWORD_RESET_CONFIRM_SUCCESS
});
} catch (err) {
dispatch({
type: PASSWORD_RESET_CONFIRM_FAIL
});
}
};
export const logout = () => dispatch => {
dispatch({
type: LOGOUT
});
};
Store.js
import { createStore, applyMiddleware, compose } from 'redux';
import { composeWithDevTools } from 'redux-devtools-extension';
import thunk from 'redux-thunk';
import rootReducer from './Reducers/Index';
const initialState = {};
const middleware = [thunk];
const store = createStore(
rootReducer,
initialState,
composeWithDevTools(applyMiddleware(...middleware))
);
export default store;
登录屏幕:
import * as React from "react";
import { useState } from "react";
import { redirect, Link as routerLink } from "react-router-dom";
import { connect } from "react-redux";
import { login } from "../Redux/Actions/Auth";
import CButton from "../components/Button";
import Visibility from "@mui/icons-material/Visibility";
import VisibilityOff from "@mui/icons-material/VisibilityOff";
import Box from "@mui/material/Box";
import {
Typography,
TextField,
Link,
Container,
IconButton,
InputAdornment,
Divider,
Button,
} from "@mui/material";
const Login = ({ login, isAuthenticated }) => {
const [showPassword, setShowPassword] = React.useState(false);
const handleClickShowPassword = () => setShowPassword((show) => !show);
const handleMouseDownPassword = (event) => {
event.preventDefault();
};
const [formData, setFormData] = useState({
email: "",
password: "",
});
const [formError, setFormError] = useState({});
const [Validated, setValidated] = useState(false);
const { email, password } = formData;
const onChange = (e) =>
setFormData({ ...formData, [e.target.name]: e.target.value });
const onSubmit = (e) => {
e.preventDefault();
setFormError(validate(formData));
if(Validated === true){
login(email, password);
}
};
const validate = (values) => {
const Errors = {};
const EmailRegrex = /^[A-Z0-9._%+-]+@[A-Z0-9.-]+.[A-Z]{2,}$/i;
if (!values.email) {
Errors.email = "Email is Required";
} else if (!EmailRegrex.test(values.email)) {
Errors.email = "Email address is not valid";
}
if (!values.password) {
Errors.password = "Password is Required";
}
setValidated(true)
return Errors;
};
if (isAuthenticated) {
return redirect("/");
}else{
console.log(typeof(isAuthenticated))}
return (
<Container component="main" maxWidth="xs">
<Box
sx={{
marginTop: 8,
display: "flex",
flexDirection: "column",
alignItems: "center",
}}
>
<Typography component="h1" variant="h1">
Sign in
</Typography>
<Box component="form" onSubmit={(e) => onSubmit(e)} sx={{ mt: 1 }}>
<TextField
margin="normal"
helperText={formError.email}
fullWidth
id="email"
label="Email Address"
name="email"
autoComplete="email"
autoFocus
onChange={(e) => onChange(e)}
value={formData.email}
error={formError.email ? true : false}
/>
<TextField
margin="normal"
helperText={formError.password}
error={formError.password ? true : false}
fullWidth
name="password"
label="Password"
value={formData.password}
type={showPassword ? "text" : "password"}
InputProps={{
endAdornment: (
<InputAdornment position="end">
<IconButton
color="primary"
aria-label="toggle password visibility"
onClick={handleClickShowPassword}
onMouseDown={handleMouseDownPassword}
edge="end"
>
{showPassword ? <VisibilityOff /> : <Visibility />}
</IconButton>
</InputAdornment>
),
}}
id="password"
autoComplete="current-password"
onChange={(e) => onChange(e)}
/>
<Box
sx={{
display: "flex",
mt: 1,
justifyContent: "flex-end",
}}
>
<Link component={routerLink} to="/Pass-Reset" variant="body2">
Forgot password?
</Link>
</Box>
<CButton props="login" />
<Divider
sx={{
my: 3,
}}
>
OR
</Divider>
<Button
fullWidth
variant="outlined"
sx={{
display: "flex",
justifyContent: "center",
alignItems: "center",
my: 4,
p: 1,
}}
>
<Box
sx={{
display: "flex",
mx: 2,
alignItems: "center",
}}
>
<img
width="35"
height="35"
src="https://upload.wikimedia.org/wikipedia/commons/5/53/Google_%22G%22_Logo.svg"
alt="google icon"
/>
</Box>
<Box>
<Typography variant="body1" component="p">
Sign in with Google
</Typography>
</Box>
</Button>
<Box
sx={{
display: "flex",
justifyContent: "center",
}}
>
<Link component={routerLink} to="/Signup" variant="body2">
{"Don't have an account? Sign Up"}
</Link>
</Box>
</Box>
</Box>
</Container>
);
};
function mapStateToProps(state) {
const isAuthenticated = state.auth.isAuthenticated;
return {isAuthenticated}
}
export default connect(mapStateToProps, { login })(Login);
显示enter image description here时出错
以下是发生此错误的最常见原因,
- 您正尝试直接渲染对象。检查渲染数据的组件,并确保您没有尝试直接渲染对象。如果是,你需要将对象转换为字符串或其他类型的数据,React可以渲染。
- 你正在传递一个对象作为 prop 。检查传递给组件的props,确保没有直接传递对象。如果是,则需要在将对象作为prop传递之前将其转换为字符串或其他类型的数据。
- 您正在尝试呈现数组。React允许你渲染一个React元素数组,但不是一个对象数组。如果你试图呈现一个数组,请确保数组中的每个元素都是React元素。
- 你正在呈现一个不返回任何东西的组件。确保你渲染的组件返回一个有效的React元素。如果组件没有返回任何内容,React将抛出“objects are not valid as a React child”错误。
但我既不是在渲染数组,也不是对象。在我的代码行,我检查状态,如果它是真的,删除这段代码和错误diss〈出现,但我需要这个功能来重定向用户。
if (isAuthenticated) {
return redirect("/");
}else{
console.log(typeof(isAuthenticated))}
2条答案
按热度按时间dffbzjpn1#
我在
Login
组件中看到的唯一奇怪或不正确的地方是从render函数返回重定向响应对象。redirect
是一个实用程序函数,仅用于数据路由器的loader
和action
函数。它返回一个Response
对象,该对象是Login
组件试图呈现的对象。它基本上返回以下要呈现的内容,这不是有效的JSX:
有关更多详细信息,请参阅源代码和
redirect
文档。如果要实现导航操作,则应导入
useNavigate
钩子并从useEffect
钩子发出命令式重定向或回调或导入并呈现[
Navigate][3]
组件以发出声明性重定向。lndjwyie2#
以下是我更新的内容:
现在运行得很完美