Как я могу заставить компонент реагировать обновить из файла JavaScript - PullRequest
0 голосов
/ 10 апреля 2019

Я пытаюсь получить компонент реагирования для отображения списка элементов, которые были получены из серверной части с помощью веб-сокетов.однако, так как мой файл websockets.js находится за пределами иерархии реагирования, список фактически никогда не обновляется, и поэтому элементы не отображаются.

Пока я пытался добавить публичный массив "проектов"к файлу websocketservice.js, а затем ссылки на этот список внутри моего компонента реакции.однако, он никогда не обновляется, даже когда websocket возвращается со своими собранными значениями.

websocketservice.js

class WebSocketService{

projects = []

    static getInstance() {
        if(!WebSocketService.instance){
            WebSocketService.instance = new WebSocketService();
        }
        return WebSocketService.instance;
    }

    constructor() {
        this.socketRef = null;
    }

    connect() {
        const path = 'ws://127.0.0.1:8000/ws/wspingpong/';
        this.socketRef = new WebSocket(path);
        this.socketRef.onopen = () => {
            console.log('websocket opened');
            this.sendTestMessage();
        };

        this.socketRef.onmessage = e => {
            console.log("message recieved: " + e.data);
            this.messageRecieved(e.data)
        }

        this.socketRef.onerror = e => {
            console.log(e.onmessage);
        }

        this.socketRef.onclose = () => {
            console.log('websocket is closed');
            this.connect();
        }
    }

    sendMessage(data){
        try{
            this.socketRef.send(JSON.stringify(...data))
        }catch(err){
            console.log(err.message)
        }
    }

    messageRecieved(data) {
        const parsedData = JSON.parse(data);
        const command = parsedData.command;
        if(command === "STC-test"){
            console.log("succesfully recieved a testmessage from the server");
        }
        if(command === "STC-login"){
            console.log("succesfully logged in, redirecting...")
            console.log(parsedData.message)
            this.loggedUser = {
                username: parsedData.message["username"],
                email: parsedData.message["email"]
            }
            history.push("/project")
        }
        if(command === "STC-getprojects"){
            console.log(parsedData.message)
            this.projects = parsedData.message
        }
    }

выше console.log(parsedData.message) правильно показывает список проектов

    getProjects(){
        console.log("getting projects....")
        if(this.loggedUser != null){
            var dict = [];
            dict.push({
                command: "CTS-getprojects",
                message: ""
            })
            this.sendMessage(dict)
        }else{
            console.log("no user logged in, unable to retrieve projects.")
        }
    }

ProjectSelect.tsx

export default class ProjectSelect extends React.Component<Iprops>{

    constructor(props: Iprops) {
        super(props)
    }
   render() {
        return (
            <div>
                {
                    WebsocketInstance.loggedUser != null ?
                        <div>
                            <h3>ProjectSelect, welcome user: {WebsocketInstance.loggedUser.username}</h3>
                            {WebsocketInstance.projects.map((name: any) => <span>name: {name}</span>)}
                            <label>Project Name:</label>
                            <input onChange={e => this.setState({ projectname: e.target.value })}></input>
                            <button onClick={() => this.createProject()}>Create a new project</button>

                        </div>
                        :
                        null
                }


            </div>
        )
    }

    createProject() {
        WebsocketInstance.createProject(this.state.projectname)
    }

РЕДАКТИРОВАТЬ попытка исправить:

 constructor(props: Iprops) {
        super(props)
        this.state = {
            projectnames: []
        }
        this.setState({
            projectnames: WebsocketInstance.projects
        })
}

а затем в методе рендеринга я добавил: {this.state.projectnames.map((name: any) => <span>name: {name}</span>)}

это, однако, не сработало

Моя цель состоит в том, чтобы как только веб-сокет обновил список с собранными значениями, компонент реагированияобновляется и отображает список значений

Ответы [ 2 ]

0 голосов
/ 12 апреля 2019

Мне удалось решить эту проблему, дав моему websocketinstance метод обратного вызова:

projectselect.tsx

constructor(props: Iprops) {
        super(props)
        this.state = {
            projectnames: [],
            projectname: ""

        }
        WebsocketInstance.callback = this.getProjectsCallback
        WebsocketInstance.getProjects()
    }
    renderMessages = (messages:any) => {
        return messages.map((message:any) => (
            <div>
            <span>{message["projectname"]}</span>
            <button onClick={() => this.openProject(message["id"])}>Load project</button>
            </div>
        ))
    }

    getProjectsCallback = (messages:any) => {
        this.setState({
            projectnames: messages
        })
    }

когда обратный вызов вызывается из веб-сокета и ему выдается новый список, я обновляю состояние и реагирую, автоматически переопределяет компонент.

websocket.js

messageRecieved(data) {
        const parsedData = JSON.parse(data);
        const command = parsedData.command;
        if(command === "STC-test"){
            console.log("succesfully recieved a testmessage from the server");
        }
        if(command === "STC-login"){
            console.log("succesfully logged in, redirecting...")
            console.log(parsedData.message)
            this.loggedUser = {
                username: parsedData.message["username"],
                email: parsedData.message["email"]
            }
            history.push("/project")
        }
        if(command === "STC-getprojects"){
            console.log(parsedData.message)
            this.callback(parsedData.message)
        }
    }
0 голосов
/ 10 апреля 2019

Я бы взял возврат от WebsocketInstance.createProject(this.state.projectname) и сделал бы что-то вроде const myData = WebsocketInstance.createProject(this.state.projectname); this.setState({webSocitReturn: myData})

Шаблон для обновления состояния / реквизита для его обновления. Постарайтесь использовать API реакции как можно больше, чтобы получить желаемый результат.

Кроме того, имейте в виду, что приведенный выше пример кода требует некоторой обработки, чтобы учесть асинхронность.

РЕДАКТИРОВАТЬ: если это не работает, вот сообщение в блоге о сокетах и ​​реагировать. https://blog.logrocket.com/beyond-rest-using-websockets-for-two-way-communication-in-your-react-app-884eff6655f5

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...