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

How can i force a react component to refresh from a javascript file

我正在尝试让一个反应组件显示使用 websockets 从后端检索到的项目列表。然而,由于我的 websockets.js 文件在反应层次结构之外,因此列表实际上从未刷新,因此不会显示项目。

到目前为止,我尝试的是将 "projects" 的 public 数组添加到 websocketservice.js 文件,然后在我的 React 组件中引用此列表。然而,即使 websocket returns 具有其收集的值,它也永远不会刷新。

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

但是这没有用

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

我会从 WebsocketInstance.createProject(this.state.projectname) 中取出 return 并做类似 const myData = WebsocketInstance.createProject(this.state.projectname); this.setState({webSocitReturn: myData})

的事情

模式是更新state/props让它刷新。尝试尽可能多地投入反应 API 以获得所需的结果。

此外,请记住我放置的上述代码示例需要一些修改以解决异步问题。

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

我通过给我的 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 调用回调并获得新列表时,我会更新状态,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)
        }
    }