我正在试图弄清楚如何根据外部事件获取要更新的组件的状态,在这种情况下,外部事件是Elixir Phoenix频道下的消息。
基本上,我有一个简单的h1标签,它必须始终反映进入频道的最新内容。所以有两个相互关联的问题:
a)如何将频道导入组件?到目前为止,我已经通过将频道作为道具来完成。
b)如何处理进入组件内部通道的消息?我的“this.state.chan.on”不起作用,看起来很笨拙。
import socket from "./socket"
import React from "react"
import ReactDOM from "react-dom"
socket.connect()
// Now that you are connected, you can join channels with a topic:
let channel = socket.channel("topic:subtopic", {})
channel.join()
.receive("ok", resp => { console.log("Joined successfully", resp) })
.receive("error", resp => { console.log("Unable to join", resp) })
class HelloWorld extends React.Component {
state = {
chan: this.props.channel,
mess: this.props.message
}
this.state.chan.on("new_message", payload => {
this.setState(prevstate => {
return {mess: ${payload.body}}
});
})
componentDidMount = () => {
console.log("did mount Hello World")
}
render = () => {
return (<h1>{this.state.mess}</h1>)
}
}
ReactDOM.render(
<HelloWorld message={1} channel={channel}/>,
document.getElementById("hello-world")
)
这种做法的可接受方式是什么?如何从通道或套接字或者在响应之外和用户界面之外生成的任何内容中获取消息,以影响组件的状态,以及相关的,如何将外部事件传递到组件中?将通道放入组件是否正确?因为这似乎也限制了通道的输出只影响该组件,而不是我可能希望它影响的其他独立组件。
编辑: 这是编译错误消息。是的,我知道我的JS可能不正确,但我在第一个this.state.chan.on上发现语法错误:
17:55:13 - error: Compiling of web/static/js/app.js failed. L40:6 Unexpected token
38 | }
39 |
> 40 | this.state.chan.on(
| ^
41 |
42 | componentDidMount = () => {
43 | console.log("did mount Hello World")
Stack trace was suppressed. Run with `LOGGY_STACKS=1` to see the trace.
18:07:20 - error: Compiling of web/static/js/app.js failed. L40:6 Unexpected token
38 | }
39 |
> 40 | this.state.chan.on("new_message", payload => {
| ^
41 | this.setState(prevstate => {
42 | return {mess: ${payload.body}}
43 | });
Stack trace was suppressed. Run with `LOGGY_STACKS=1` to see the trace.
18:07:22 - error: Compiling of web/static/js/app.js failed. L40:6 Unexpected token
38 | }
39 |
> 40 | this.state.chan.on("new_message", payload => {
| ^
41 | this.setState(prevstate => {
42 | return {mess: ${payload.body}}
43 | });
Stack trace was suppressed. Run with `LOGGY_STACKS=1` to see the trace.
答案 0 :(得分:2)
你不能在函数之外的类体中拥有this.state.chan.on(...)
。您可以将所有这些代码放在构造函数中。此外,您的setState
调用包含语法错误,可以简化为使用对象作为参数。以下是构造函数的外观:
class HelloWorld extends React.Component {
constructor(props) {
super();
this.state = {
chan: props.channel,
mess: props.message
};
this.state.chan.on("new_message", payload => {
this.setState({mess: payload.body});
});
}
...
}
但是有一个问题。即使从DOM卸载此组件,on
回调也会一直被触发。您应订阅componentDidMount
中的邮件并取消订阅componentWillUnmount
:
class HelloWorld extends React.Component {
constructor(props) {
super();
this.state = {
chan: props.channel,
mess: props.message
};
}
componentDidMount() {
const ref = this.state.chan.on("new_message", payload => {
this.setState({mess: payload.body});
});
this.setState({ref: ref});
}
componentWillUnmount() {
this.state.chan.off("new_message", this.state.ref);
}
...
}