我如何强制React组件从javascript文件刷新

时间:2019-04-10 13:40:39

标签: javascript reactjs websocket

我正在尝试获取一个react组件,以显示使用websockets从后端检索到的项目的列表。但是,由于我的websockets.js文件不在react层次结构之外,因此该列表从未真正刷新过,因此不会显示项目。

到目前为止,我一直在尝试将一个“项目”的公共数组添加到websocketservice.js文件中,然后在我的react组件中引用此列表。但是,即使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)
    }

EDIT 尝试修复:

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

,然后在我添加的render方法中: {this.state.projectnames.map((name: any) => <span>name: {name}</span>)}

但是这不起作用

我的目标是,只要网络套接字使用收集的值更新列表,反应组件就会刷新并显示值列表

2 个答案:

答案 0 :(得分:0)

我会从WebsocketInstance.createProject(this.state.projectname)那里获得回报,并做类似 const myData = WebsocketInstance.createProject(this.state.projectname); this.setState({webSocitReturn: myData})的事情

模式是更新状态/道具以使其刷新。尝试尽可能多地使用react API以获得所需的结果。

此外,请记住我上面提到的代码示例,需要进行一些修补才能解决异步问题。

编辑:如果不起作用,这是有关套接字和响应的博客文章。 https://blog.logrocket.com/beyond-rest-using-websockets-for-two-way-communication-in-your-react-app-884eff6655f5

答案 1 :(得分:0)

我设法通过给我的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调用回调并获得新列表时,我会更新状态并做出反应,从而自动重新呈现组件。

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