首页 > 解决方案 > 我如何强制反应组件从 javascript 文件中刷新

问题描述

我正在尝试获取一个反应组件来显示已使用 websockets 从后端检索到的项目列表。但是,由于我的 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.")
        }
    }

项目选择.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>)}

然而这并没有奏效

我的目标是,一旦 websocket 使用收集的值更新列表,react 组件就会刷新并显示值列表

标签: javascriptreactjswebsocket

解决方案


我设法通过给我的 websocketinstance 一个回调方法来解决这个问题:

项目选择.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 调用回调并获得一个新列表时,我会更新状态并且 react 将自动重新渲染组件。

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

推荐阅读