Where should long running processes "live" in a react+redux app?
长期运行的流程应该在react + redux应用程序中“活动”?
For a simple example, consider a class which sends and receives messages over a websocket:
举一个简单的例子,考虑一个通过websocket发送和接收消息的类:
class WebsocketStreamer {
sendMessage(message) {
this.socket.send(…);
}
onMessageReceive(event) {
this.dispatch({
type: "STREAMER_RECV",
message: event.data,
})
}
}
How should the lifecycle of this class be managed?
如何管理这个类的生命周期?
My first instinct is to keep it on the store
:
我的第一直觉就是把它放在商店里:
var stores = {
streamer: function(state={}, action) {
if (action.type == "@@INIT")
return { streamer: new WebsocketStreamer() }
if (action.type == "STREAMER_SEND")
state.streamer.sendMessage(action.message)
return state;
}
}
But, aside from being a bit strange, there's also no way for the WebsocketStreamer
to get access to the dispatch()
function, and it breaks hot reloading.
但是,除了有点奇怪之外,WebsocketStreamer也无法访问dispatch()函数,并且它会破坏热重新加载。
Another potential solution is to keep it in a global somewhere:
另一个可能的解决方案是将其保持在某个地方:
const streamer = new WebsocketStreamer();
But that has obvious testability implications, and breaks hot reloading too.
但这具有明显的可测试性含义,并且也打破了热重新加载。
So, where should a long running process live in a react + redux app?
那么,一个长时间运行的进程应该放在react + redux应用程序中?
Note: I realize that this simple example could be built with just stores + action providers. But I would specifically like to know where long-lived processes should exist in situations where they exist.
注意:我意识到这个简单的例子可以只使用商店+动作提供者构建。但我特别想知道在它们存在的情况下应该存在多长时间的过程。
2 个解决方案
#1
20
In my experience, there are two options. First, you can pass store to any non-Redux code and dispatch actions from here. I've did this with socket connection and all was fine. Second, if you need socket or whatever to change with redux actions, it looks like a good idea to put connection and it's management in custom middleware. You'll have access to store API as well as will be informed on all actions dispatching, so could do anything you need to.
根据我的经验,有两种选择。首先,您可以将商店传递给任何非Redux代码并从此处调度操作。我用插座连接完成了这一切,一切都很好。其次,如果你需要套接字或者用redux动作改变什么,那么将连接和它的管理放在自定义中间件中似乎是一个好主意。您可以访问商店API,并将获得所有调度操作的通知,因此可以执行您需要的任何操作。
#2
2
I'm doing something similar with websockets. In my case, I simply wrap the websocket client in a React component that renders null and inject it as close to the root as possible.
我正在做与websockets类似的事情。在我的例子中,我只是将websocket客户端包装在一个React组件中,该组件呈现null并将其尽可能靠近根注入。
<App>
<WebSocketClientThingy handlers={configuredHandlers}/>
....
</App>
Here's a quick example. It's pretty naive, but get's stuff done.
这是一个简单的例子。这很天真,但是完成了。
https://github.com/trbngr/react-example-pusher
Quick note: The websocket doesn't live in the store. It's simply there and publishes actions.
快速说明:websocket不在商店中。它就在那里并发布行动。
EDIT: I decided to explore setting the client (long-lived object) into the global state. I gotta say that I'm a fan of this approach.
编辑:我决定探索将客户端(长期存在的对象)设置为全局状态。我得说我是这种方法的粉丝。
https://github.com/trbngr/react-example-pusher/tree/client_as_state
#1
20
In my experience, there are two options. First, you can pass store to any non-Redux code and dispatch actions from here. I've did this with socket connection and all was fine. Second, if you need socket or whatever to change with redux actions, it looks like a good idea to put connection and it's management in custom middleware. You'll have access to store API as well as will be informed on all actions dispatching, so could do anything you need to.
根据我的经验,有两种选择。首先,您可以将商店传递给任何非Redux代码并从此处调度操作。我用插座连接完成了这一切,一切都很好。其次,如果你需要套接字或者用redux动作改变什么,那么将连接和它的管理放在自定义中间件中似乎是一个好主意。您可以访问商店API,并将获得所有调度操作的通知,因此可以执行您需要的任何操作。
#2
2
I'm doing something similar with websockets. In my case, I simply wrap the websocket client in a React component that renders null and inject it as close to the root as possible.
我正在做与websockets类似的事情。在我的例子中,我只是将websocket客户端包装在一个React组件中,该组件呈现null并将其尽可能靠近根注入。
<App>
<WebSocketClientThingy handlers={configuredHandlers}/>
....
</App>
Here's a quick example. It's pretty naive, but get's stuff done.
这是一个简单的例子。这很天真,但是完成了。
https://github.com/trbngr/react-example-pusher
Quick note: The websocket doesn't live in the store. It's simply there and publishes actions.
快速说明:websocket不在商店中。它就在那里并发布行动。
EDIT: I decided to explore setting the client (long-lived object) into the global state. I gotta say that I'm a fan of this approach.
编辑:我决定探索将客户端(长期存在的对象)设置为全局状态。我得说我是这种方法的粉丝。
https://github.com/trbngr/react-example-pusher/tree/client_as_state