Reactjs react钩子会从Django Rest API自动生成相关输入字段下的错误消息
我想在React前端自动显示来自Django Rest Api的每个错误消息。我想用signup身份验证函数测试我的概念,在修复它之后,我想在从django API获取数据或将数据导入django API的每个组件中使用这个概念 以下是我的App.js注册用户进行测试:Reactjs react钩子会从Django Rest API自动生成相关输入字段下的错误消息,reactjs,django-rest-framework,react-hooks,use-effect,extract-error-message,Reactjs,Django Rest Framework,React Hooks,Use Effect,Extract Error Message,我想在React前端自动显示来自Django Rest Api的每个错误消息。我想用signup身份验证函数测试我的概念,在修复它之后,我想在从django API获取数据或将数据导入django API的每个组件中使用这个概念 以下是我的App.js注册用户进行测试: import React, { useState } from "react"; export default function Signup() { const [username, setUsern
import React, { useState } from "react";
export default function Signup() {
const [username, setUsername] = useState("");
const [email, setEmail] = useState("");
const [password1, setPassword1] = useState("");
const [password2, setPassword2] = useState("");
const [user, setUser] = useState("");
function handleEmail(evt) {
setEmail(evt.target.value);
}
function handleUsername(evt) {
setUsername(evt.target.value);
}
function handlePassword1(evt) {
setPassword1(evt.target.value);
}
function handlePassword2(evt) {
setPassword2(evt.target.value);
}
function handle_signup(evt) {
evt.preventDefault();
fetch("http://127.0.0.1:8000/api/v1/rest-auth/registration/", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ username, email, password1, password2 }),
})
.then((res) => res.json())
.then((json) => {
localStorage.setItem("token", json.key);
console.log(json);
setUser(json.username);
})
.catch((err) => {
if(err.res){
console.log(err.res.username)
console.log(err.res.email);
console.log(err.res.password1);
console.log(err.res.password2);
}else if(err.res){
console.log(err.res)
}else{
console.log('Error',err.message)
}
console.log(err.config);
});
}
return (
<form onSubmit={(evt) => handle_signup(evt, setUser())}>
<label htmlFor="register-username">Username:</label>
<input
type="text"
value={username}
onChange={handleUsername}
name="register-username"
id="register-username"
/>
<label htmlFor="register-email">Email:</label>
<input
type="text"
value={email}
onChange={handleEmail}
name="register-username"
id="register-username"
/>
<label htmlFor="register-password1">Password1:</label>
<input
type="password1"
value={password1}
onChange={handlePassword1}
name="register-password1"
id="register-password1"
/>
<label htmlFor="register-password2">password2:</label>
<input
type="password2"
value={password2}
onChange={handlePassword2}
name="register-password2"
id="register-password2"
/>
<input type="submit" value="Register" />
</form>
);
}
import React,{useState}来自“React”;
导出默认函数注册(){
const[username,setUsername]=useState(“”);
const[email,setEmail]=useState(“”);
const[password1,setPassword1]=useState(“”);
const[password2,setPassword2]=useState(“”);
const[user,setUser]=useState(“”);
功能handleEmail(evt){
setEmail(evt.target.value);
}
函数handleUsername(evt){
setUsername(evt.target.value);
}
功能手柄密码1(evt){
setPassword1(evt.target.value);
}
功能手柄密码2(evt){
setPassword2(evt.target.value);
}
函数句柄注册(evt){
evt.preventDefault();
取回(“http://127.0.0.1:8000/api/v1/rest-授权/注册/“{
方法:“张贴”,
标题:{
“内容类型”:“应用程序/json”,
},
正文:JSON.stringify({username,email,password1,password2}),
})
.然后((res)=>res.json())
。然后((json)=>{
setItem(“token”,json.key);
log(json);
setUser(json.username);
})
.catch((错误)=>{
如果(错误恢复){
console.log(err.res.username)
console.log(err.res.email);
console.log(err.res.password1);
console.log(err.res.password2);
}else if(err.res){
console.log(err.res)
}否则{
console.log('Error',err.message)
}
console.log(err.config);
});
}
返回(
handle_注册(evt,setUser())}>
用户名:
电邮:
密码1:
密码2:
);
}
在Useffect中,我尝试在用户名、电子邮件、密码1、密码2等相关输入框下显示每个错误消息,我尝试通过React hook表单来实现,但这就像从前端插入错误消息一样。但我想显示来自后端的实际错误消息。在开发工具中,当我通过在输入框中放置错误的信息来尝试上面的代码时,它只会显示POST:400(错误请求)
如何在每个输入框下显示此类错误消息,如用户名存在或电子邮件地址无效,或密码必须至少为8,这在Django Rest API的典型错误消息中是典型的?
仅供参考:如果输入框填写正确,此代码可以注册任何用户。下面的代码来自我的文章。它正在使用
react引导
。这是一个关于用户名
和密码
的简单示例,但您可以轻松地扩展它
如果存在已知错误(),我会检查它是否有关于用户名
或密码
的消息。如果是,则我为FormControl.Feedback
设置了一条错误消息。如果您不想使用react bootstrap
,只需在div
中创建一个小的红色文本,并仅在设置了错误消息(非空)时使其可见即可
//前端/src/components/signup/signup.js文件
从“React”导入React,{Component};
从“react router dom”导入{withRouter};//新进口
从“react redux”导入{connect};//新进口
从“道具类型”导入道具类型;//新进口
从“react router dom”导入{Link};
进口{
集装箱,
按钮
一行
上校,
形式,
窗体控件
}从“反应引导”;
从“/SignupActions”/”导入{signupNewUser}新进口
类注册扩展了组件{
建造师(道具){
超级(道具);
此.state={
用户名:“”,
密码:“
};
}
onChange=e=>{
this.setState({[e.target.name]:e.target.value});
};
//更新函数以调用操作
onSignupClick=()=>{
常量用户数据={
用户名:this.state.username,
密码:this.state.password
};
this.props.signupNewUser(userData);//({
createUser:state.createUser
});
导出默认连接(MapStateTops{
注册新用户
})(使用路由器(注册));
下面的代码来自我的文章。它使用的是
react bootstrap
。这是一个带有username
和password
的简单示例,但您可以轻松扩展它
如果存在已知错误()我检查它是否有username
或password
的消息。如果是,则我为FormControl.Feedback
设置一条错误消息。如果您不想使用react bootstrap
,您只需在div
中创建一个小的红色文本,并且只有在设置了错误消息(不是空的)时才可以看到它
//前端/src/components/signup/signup.js文件 从“React”导入React,{Component}; 从“react router dom”导入{withRouter};//新导入 从“react redux”导入{connect};//新导入 从“道具类型”导入道具类型;//新建导入 从“react router dom”导入{Link}; 进口{ 集装箱, 按钮 一行 上校, 形式, 窗体控件 }从“反应引导”; 从“/SignupActions”;//新导入导入{signupNewUser} 类注册扩展了组件{ 建造师(道具){ 超级(道具); 此.state={ 用户名:“”, 密码:“ }; } onChange=e=>{ this.setState({[e.target.name]:e.target.value}); }; //更新函数以调用操作 onSignupClick=()=>{ 常量用户数据={ 用户名:this.state.username, 密码:this.state.password }; this.props.signupNewUser(userData);//({ createUser:state.createUser }); 导出默认连接(MapStateTops{ 注册新用户 })(使用路由器(注册));
// frontend/src/components/SignupReducer.js // import needed actions import { CREATE_USER_ERROR, CREATE_USER_SUBMITTED, CREATE_USER_SUCCESS } from "./SignupTypes"; // define the initial state of the signup store const initialState = { usernameError: "", passwordError: "", isSubimtted: false }; // define how action will change the state of the store export const signupReducer = (state = initialState, action) => { switch (action.type) { case CREATE_USER_SUBMITTED: return { usernameError: "", passwordError: "", isSubimtted: true }; case CREATE_USER_ERROR: const errorState = { usernameError: "", passwordError: "", isSubimtted: false }; if (action.errorData.hasOwnProperty("username")) { errorState.usernameError = action.errorData["username"]; } if (action.errorData.hasOwnProperty("password")) { errorState.passwordError = action.errorData["password"]; } return errorState; case CREATE_USER_SUCCESS: return { usernameError: "", passwordError: "", isSubimtted: false }; default: return state; } }
// frontend/src/components/signup/SignupActions.js
import axios from "axios";
import { toast } from "react-toastify";
import { isEmpty } from "../../utils/Utils";
import {
CREATE_USER_ERROR,
CREATE_USER_SUBMITTED,
CREATE_USER_SUCCESS
} from "./SignupTypes";
export const signupNewUser = userData => dispatch => {
dispatch({ type: CREATE_USER_SUBMITTED }); // set submitted state
axios
.post("/api/v1/users/", userData)
.then(response => {
toast.success(
"Account for " +
userData.username +
" created successfully. Please login."
);
dispatch({ type: CREATE_USER_SUCCESS });
})
.catch(error => {
if (error.resposne) {
// The request was made and the server responded with a status code
// that falls out of the range of 2xx
toast.error(JSON.stringify(error.response.data));
dispatch({
type: CREATE_USER_ERROR,
errorData: error.response.data
});
} else if (error.message) {
// the error message is available,
// let's display it on error toast
toast.error(JSON.stringify(error.message));
} else {
// strange error, just show it
toast.error(JSON.stringify(error));
}
});
};
// frontend/src/components/signup/Signup.js file
import React, { Component } from "react";
import { withRouter } from "react-router-dom"; // new import
import { connect } from "react-redux"; // new import
import PropTypes from "prop-types"; // new import
import { Link } from "react-router-dom";
import {
Container,
Button,
Row,
Col,
Form,
FormControl
} from "react-bootstrap";
import { signupNewUser } from "./SignupActions"; // new import
class Signup extends Component {
constructor(props) {
super(props);
this.state = {
username: "",
password: ""
};
}
onChange = e => {
this.setState({ [e.target.name]: e.target.value });
};
// update function to call the action
onSignupClick = () => {
const userData = {
username: this.state.username,
password: this.state.password
};
this.props.signupNewUser(userData); // <-- signup new user request
};
render() {
return (
<Container>
<Row>
<Col md="4">
<h1>Sign up</h1>
<Form>
<Form.Group controlId="usernameId">
<Form.Label>User name</Form.Label>
<Form.Control
isInvalid={this.props.createUser.usernameError}
type="text"
name="username"
placeholder="Enter user name"
value={this.state.username}
onChange={this.onChange}
/>
<FormControl.Feedback type="invalid">
{this.props.createUser.usernameError}
</FormControl.Feedback>
</Form.Group>
<Form.Group controlId="passwordId">
<Form.Label>Your password</Form.Label>
<Form.Control
isInvalid={this.props.createUser.passwordError}
type="password"
name="password"
placeholder="Enter password"
value={this.password}
onChange={this.onChange}
/>
<Form.Control.Feedback type="invalid">
{this.props.createUser.passwordError}
</Form.Control.Feedback>
</Form.Group>
</Form>
<Button color="primary" onClick={this.onSignupClick}>
Sign up
</Button>
<p className="mt-2">
Already have account? <Link to="/login">Login</Link>
</p>
</Col>
</Row>
</Container>
);
}
}
// connect action and reducer
// replace
// export default Signup;
// with code below:
Signup.propTypes = {
signupNewUser: PropTypes.func.isRequired,
createUser: PropTypes.object.isRequired
};
const mapStateToProps = state => ({
createUser: state.createUser
});
export default connect(mapStateToProps, {
signupNewUser
})(withRouter(Signup));