Reactjs react钩子会从Django Rest API自动生成相关输入字段下的错误消息

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

我想在React前端自动显示来自Django Rest Api的每个错误消息。我想用signup身份验证函数测试我的概念,在修复它之后,我想在从django API获取数据或将数据导入django API的每个组件中使用这个概念

以下是我的App.js注册用户进行测试:

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));