React - TypeError: Невозможно прочитать свойство undefined - PullRequest
0 голосов
/ 26 мая 2019

У меня есть два очень похожих компонента React, делающих внутренние запросы к Flask:


REACT

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 возвращает «данные» в качестве моего шаблона на сервере, 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>
    ....

, и поэтому я получаю следующую ошибку при рендеринге Seeds:

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

Колба

seed.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 Ответ

1 голос
/ 26 мая 2019

Запрос 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)
     // ....
     }
...