反应-TypeError:无法读取未定义的属性

时间:2019-05-25 22:19:57

标签: reactjs flask axios

我有两个非常相似的React组件向Flask发出后端请求:


反应

UserStatus.jsx

class UserStatus extends Component {
  constructor (props) {
    super(props);
    this.state = {
      user:'',      
      email: '',
      id: '',
      username: '',
      active: '',
      admin: ''    
    };
  };
  componentDidMount() {
    if (this.props.isAuthenticated) {
      this.getUserStatus();
    }
  };
  getUserStatus(event) {
    const options = {
      url: `${process.env.REACT_APP_WEB_SERVICE_URL}/auth/status`,
      method: 'get',
      headers: {
        'Content-Type': 'application/json',
        Authorization: `Bearer ${window.localStorage.authToken}`
      }
    };
    return axios(options)
    .then((res) => { 
      console.log(res.data)  
      console.log(res.data.data) 
      this.setState({
        user: res.data.data.user,
        email: res.data.data.email,
        id: res.data.data.id,
        username: res.data.data.username,
        active: String(res.data.data.active),
        admin: String(res.data.data.admin),
      })
    })
    .catch((error) => { console.log(error); });
  };
  render() {
    if (!this.props.isAuthenticated) {
      return (
        <p>You must be logged in to view this. Click <Link to="/login">here</Link> to log back in.</p>
      )
    };
    return (
      <div>
      <h1 className="title is-1"><font color="#C86428">Current User</font></h1>
      <hr/><br/>
      <ul>
        <li><strong><font color="#C86428">User:</font></strong><font color="white"> {this.state.coffeeshop} </font></li>
        <li><strong><font color="#C86428">User ID:</font></strong><font color="white"> {this.state.id} </font></li>
        <li><strong><font color="#C86428">Email:</font></strong><font color="white"> {this.state.email} </font></li>
        <li><strong><font color="#C86428">Username:</font></strong><font color="white"> {this.state.username} </font></li>
        <li><strong><font color="#C86428">Active:</font></strong><font color="white"> {this.state.active} </font></li>
        <li><strong><font color="#C86428">Admin:</font></strong><font color="white"> {this.state.admin} </font></li> 
      </ul>
    </div>
    )
  };
};

export default UserStatus;

Seeds.jsx

class Seeds extends Component{
  constructor (props) {
    super(props);
    this.state = {
      user:'',      
      email: '',
      id: '',
      username: '',
      active: '',
      admin: ''    
    };
  };
  componentDidMount() {
    if (this.props.isAuthenticated) {
      this.getUserStatus();
    }
  };
  getUserStatus(event) {
    const options = {
      url: `${process.env.REACT_APP_WEB_SERVICE_URL}/seeds`,
      method: 'get',
      headers: {
        'Content-Type': 'application/json',
        Authorization: `Bearer ${window.localStorage.authToken}`
      }
    };
    return axios(options)
    .then((res) => {
    console.log(res.data)  
      console.log(res.data.data) 
      this.setState({
        user: res.data.data.user,
        email: res.data.data.email,
        id: res.data.data.id,
        username: res.data.data.username,
        active: String(res.data.data.active),
        admin: String(res.data.data.admin),
      })
    })
    .catch((error) => { console.log(error); });
  };

    render(){
        return (
            <div className="form">
                <form action="http://localhost:5000/seeds" method="get, post">
                </form>
            </div>
        );
    }
}

export default Seeds;

但是 UserStatus 返回“数据”作为对象:

{data: {…}, message: "success", status: "success"}

种子在后端seeds.html返回“数据”作为我的模板:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Brandio Coffee Browser</title>
    <link rel="stylesheet" href="/static/css/bootstrap.css">
    <link rel="stylesheet" href="/static/css/mug.css">

    <script src="/static/js/audiojs/audio.min.js"></script>
    <script>
      audiojs.events.ready(function() {
        var as = audiojs.createAll();
      });
    </script>
    ....

,所以在渲染种子时出现以下错误:

TypeError: Cannot read property 'user' of undefined
    at eval (Seeds.jsx:37)

烧瓶

seeds.py

seeds_bp = Blueprint('seeds', 
                     __name__, 
                     template_folder='templates', 
                     static_url_path='static') 

@seeds_bp.route('/seeds', methods=['GET', 'POST'])
def seeds():    
    user = User.query.filter_by(id=1).first()

    if user.x == []:
        return render_template('seeds.html')
    else:
        # business logic
        return render_template('seeds.html')


    return render_template('seeds.html')

我请问:

1-为什么这种行为上的差异?

2-如何正确呈现seeds.html后端模板页面?

1 个答案:

答案 0 :(得分:1)

axios请求期望一个json响应,但是它接收到一个html文件。查看您的客户代码:

getUserStatus(event) {
    //...
    return axios(options)
    .then((res) => {
    console.log(res.data)  
      console.log(res.data.data) 
      this.setState({
        user: res.data.data.user,
        email: res.data.data.email,
        id: res.data.data.id,
        username: res.data.data.username,
        active: String(res.data.data.active),
        admin: String(res.data.data.admin),
      })
    })
    // ...

您希望收到类似于以下内容的json响应:

data = { 
"user": "...",
"email": "...",
"id": "...",
"username": "...",
"active": "...",
"admin": "...."
}

因此,要接收JSON响应,您需要像下面那样更改后端代码:

from flask import jsonify

@seeds_bp.route('/seeds', methods=['GET', 'POST'])
def seeds(): 
    user = User.query.filter_by(id=1).first()

    if user.x == []:
        # you need to change the '...' based to the user received from the 
        # database.
        data = { "user": "...","email": "...","id": "...",
        "username": "...","active": "...","admin": "...."}
        return jsonify(data)
    else:
        # business logic
        # you need to change the '...' based to the user received from the 
        #database.
        data = { "user": "...","email": "...","id": "...",
        "username": "...","active": "...","admin": "...."}
        return jsonify(data)

    data = { "user": "...","email": "...","id": "...",
    "username": "...","active": "...","admin": "...."}
    return jsonify(data)

在客户端部分,您需要记录响应并根据响应更改代码:

getUserStatus(event) {
    //...
    return axios(options)
    .then((res) => {
     console.log(res)
     // ....
     }