我正在尝试获取一个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>)}
但是这不起作用
我的目标是,只要网络套接字使用收集的值更新列表,反应组件就会刷新并显示值列表
答案 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)
}
}