Как мне получить доступ к внутреннему маршруту, реализованному с помощью flask, с использованием реакции? - PullRequest
0 голосов
/ 27 января 2020

Я пытаюсь включить чат в моем приложении flask, используя socketio в качестве микросервиса. Прямо сейчас у меня есть файл rout.py:

main_blueprint = Blueprint("main", __name__, template_folder='../templates', static_folder='../templates')



@main.route('/', methods=['GET', 'POST'])
def index():
    """Login form to enter a room."""
    form = LoginForm()
    if form.validate_on_submit():
        session['name'] = form.name.data
        session['room'] = form.room.data
        return redirect(url_for('.chat'))
    elif request.method == 'GET':
        form.name.data = session.get('name', '')
        form.room.data = session.get('room', '')

    return render_template('index.html', form=form)


@main.route('/chat')
def chat():
    """Chat room. The user's name and room must be stored in
    the session."""
    name = session.get('name', '')
    room = session.get('room', '')
    if name == '' or room == '':
        return redirect(url_for('.index'))

    return render_template('chat.html', name=name, room=room)

Этот лог c отображает два html файла, расположенных в файле ../templates. Однако остальная часть моего приложения находится в отдельном клиентском сервисе, написанном на реаги. Я хотел бы использовать компонент реакции, такой как:

import React from "react";
import io from 'socket.io-client';

class ChatRoom extends React.Component {
    state = {
        socketData: "",
        socketStatus:"On"
    }
    componentWillUnmount() {
        this.socket.close()
        console.log("component unmounted")
    }
    componentDidMount() {
        var sensorEndpoint = "http://localhost:5002"
            this.socket = io.connect(sensorEndpoint, {
            reconnection: true,
            // transports: ['websocket']
        });
        console.log("component mounted")
            this.socket.on("responseMessage", message => {
                this.setState({'socketData': message.temperature})

                console.log("responseMessage", message)
            })

    }
    handleEmit=()=>{
        if(this.state.socketStatus==="On"){
        this.socket.emit("message", {'data':'Stop Sending', 'status':'Off'})
        this.setState({'socketStatus':"Off"})
    }
    else{        
        this.socket.emit("message", {'data':'Start Sending', 'status':'On'})
        this.setState({'socketStatus':"On"})
        }
        console.log("Emit Clicked")
    }
    render() {
        return (
            <React.Fragment>
            <div>Data: {this.state.socketData}</div>
            <div>Status: {this.state.socketStatus}</div>
            <div onClick={this.handleEmit}> Start/Stop</div>
            </React.Fragment>
        )
    }
}
export default ChatRoom;

или этот:

import React, { Component } from 'react'
import ControlBar from './ControlBar'
import Conversations from './Conversations'
import Flash from './Flash'
import io from 'socket.io-client';
import axios from 'axios';
const socket = io('http://localhost:5002')

class Chat extends Component {
    constructor (props) {
      super(props)
      this.state = {
        username: '',
        activeUsers: [],
        rooms: [],
        messages: [],
        flashNotice: ''
      }
      this.handleChange = this.handleChange.bind(this)
      this.joinRoom = this.joinRoom.bind(this)
      this.leaveRoom = this.leaveRoom.bind(this)
      this.sendMessage = this.sendMessage.bind(this)
      this.setUsername = this.setUsername.bind(this)
      this.createFlash = this.createFlash.bind(this)
      this.clearFlash = this.clearFlash.bind(this)
    }

    handleChange (event) {
      const {name, value} = event.target
      this.setState({ [name]: value })
    }

    setUsername (username) {
      const oldName = this.state.username
      if (oldName && oldName !== username) {
        socket.emit('deactivate_user', { username: oldName })
      }
      this.setState({ username }, () => {
        socket.emit('activate_user', { username: this.state.username })
      })
    }

    loadMessages () {
      const savedMessages = window.localStorage.getItem('messages')
      if (savedMessages) {
        this.setState({ messages: JSON.parse(savedMessages) || [] })
      }
    }

    setSocketListeners () {
      socket.on('message', (data) => {
        console.log(data.message)
      })

      socket.on('message_sent', (message) => {
        const room = message['room']
        this.setState({ messages: [...this.state.messages, message] }, () => {
          window.localStorage.setItem('messages', JSON.stringify(this.state.messages))
          if (this.state.rooms.indexOf(room) === -1) {
            this.setState({ rooms: [...this.state.rooms, room] })
          }
        })
      })

      socket.on('retrieve_active_users', () => {
        if (this.state.username) {
          socket.emit('activate_user', { username: this.state.username })
        }
      })

      socket.on('user_activated', (data) => {
        const user = data['user']
        const { activeUsers } = this.state
        if (activeUsers.indexOf(user) === -1 && user !== this.state.username) {
          this.setState({ activeUsers: [...activeUsers, user] }, () => {
            this.createFlash(`${user} is online`)
          })
        }
      })

      socket.on('user_deactivated', (data) => {
        const deactivatedUser = data['user']
        const { activeUsers } = this.state
        if (activeUsers.indexOf(deactivatedUser) !== -1) {
          this.setState({ activeUsers: activeUsers.filter((user) => {
            return user !== deactivatedUser
          })})
        }
      })

      socket.on('open_room', (data) => {
        const room = data['room']
        const openRooms = this.state.rooms
        const userInRoom = room.split('|').indexOf(this.state.username) !== -1
        const roomNotOpen = openRooms.indexOf(room) === -1
        if (userInRoom && roomNotOpen) {
          this.joinRoom(room, this.state.username)
        }
      })
    }

    joinRoom (room, username, partner) {
      room = room || [username, partner].sort().join('|')
      if (this.state.rooms.indexOf(room) === -1) {
        this.setState({rooms: [...this.state.rooms, room]}, () => {
          socket.emit('join_room', { username, room })
        })
      }
    }

    leaveRoom (room, username) {
      this.setState({ rooms: this.state.rooms.filter((r) => r !== room) })
    }

    sendMessage (message, room) {
      socket.emit(
        'send_message',
        {
          room,
          author: this.state.username,
          body: message,
          timeStamp: Date.now()
        }
      )
    }

    createFlash (text) {
      this.setState({flashNotice: ''}, () => {
        this.setState({flashNotice: text}, () => {
          window.setTimeout(this.clearFlash, 2500)
        })
      })
    }

    clearFlash () {
      this.setState({flashNotice: ''})
    }

    getChat() {
        return axios.get(`${process.env.REACT_APP_CHAT_SERVICE_URL}/chat`)
        .then((res) => {
            this.setState({
            exercises: res.data.data.exercises,
            currentExercise: 0,
            });
            this.renderButtons();
        })
        .catch((err) => { console.log(err); });
        };
    componentDidMount () {
      this.getChat()
      this.loadMessages()
      this.setSocketListeners()
    }

    render () {
      const {username, rooms, messages, flashNotice} = this.state

      return (
        <div className='App'>
          <div className='header'>
            {/* <img className='logo' src={logo} alt='logo' /> */}
            <h1 className='title'>Fat Chat</h1>
          </div>
          <Flash notice={flashNotice} />
          <ControlBar
            activeUsers={this.state.activeUsers}
            setUsername={this.setUsername}
            createFlash={this.createFlash}
            joinRoom={this.joinRoom} />
          <Conversations
            rooms={rooms}
            messages={messages}
            username={username}
            leaveRoom={this.leaveRoom}
            sendMessage={this.sendMessage} />
        </div>
      )
    }
  }



export default Chat;

, чтобы играть роль чата. html файл:

    <head>
        <title>Flask-SocketIO-Chat: {{ room }}</title>
        <script type="text/javascript" src="//code.jquery.com/jquery-1.4.2.min.js"></script>
        <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/socket.io/1.3.6/socket.io.min.js"></script>
        <script type="text/javascript" charset="utf-8">
            var socket;
            $(document).ready(function(){
                socket = io.connect('http://' + document.domain + ':' + location.port + '/chat');
                socket.on('connect', function() {
                    socket.emit('joined', {});
                });
                socket.on('status', function(data) {
                    $('#chat').val($('#chat').val() + '<' + data.msg + '>\n');
                    $('#chat').scrollTop($('#chat')[0].scrollHeight);
                });
                socket.on('message', function(data) {
                    $('#chat').val($('#chat').val() + data.msg + '\n');
                    $('#chat').scrollTop($('#chat')[0].scrollHeight);
                });
                $('#text').keypress(function(e) {
                    var code = e.keyCode || e.which;
                    if (code == 13) {
                        text = $('#text').val();
                        $('#text').val('');
                        socket.emit('text', {msg: text});
                    }
                });
            });
            function leave_room() {
                socket.emit('left', {}, function() {
                    socket.disconnect();

                    // go back to the login page
                    window.location.href = "{{ url_for('main.index') }}";
                });
            }
        </script>
    </head>
    <body>
        <h1>Flask-SocketIO-Chat: {{ room }}</h1>
        <textarea id="chat" cols="80" rows="20"></textarea><br><br>
        <input id="text" size="80" placeholder="Enter your message here"><br><br>
        <a href="#" onclick="leave_room();">Leave this room</a>
    </body>
</html>

В настоящее время, когда я набираю url localhost: // chat в адресной строке, я получаю html, однако, когда я пытаюсь получить доступ к маршруту, на стороне клиента с помощью ax ios я получаю jsx. Только когда я обновлю sh страницу, я получу обслуживаемый шаблон.

Я хотел бы понять, как буквально и в переносном смысле получить интерфейс и бэкэнд моего приложения на одной странице. Обе стороны не могут «договориться» о том, что должно быть отображено, и я не понимаю, должен ли я указать бэкэнду flask, чтобы он служил шаблону «реакции», или я должен сказать клиенту реакции, что он должен извлекать данные из указанного c маршрута.

Я благодарю всех за их время и отзывы. Я изо всех сил пытаюсь понять, что происходит, и надеюсь, что этот вопрос достаточно хорошо описан. Если вы хотите взглянуть на источник, он расположен по адресу:

https://github.com/smeyerhot/appster
...