Comments (5)
I'm not sure what you mean by webhooks, but here's an example of how I would write a websocket subscription and hooks for it in my app.
This is going to seem like a lot of code, but its designed like a library that you could publish and consume.
Step 1: Creating an API
If there isn't a pre-built one out there, feel free to create your own little
library for dealing with some state/logic/events outside of React.
import io from "socket.io"
function createSocket(url) {
let socket = io(url)
let handlers = []
let messages = []
socket.on("connect", () => {
socket.on("message", message => {
messages.push(message)
handlers.forEach(handler => handler(message))
})
})
let connect = () => {
socket.connect()
return () => socket.disconnect()
}
let getMessages = () => messages.slice()
let onMessage = handler => {
handlers.push(handler)
return () => {
handlers = handlers.filter(h => h !== handler)
}
}
return { connect, getMessages, onMessage }
}
Step 2. Wrapping it with React
Next, using that API, create some APIs for connecting it to React. Make state
available and subscribe to it through hooks and use context to share values.
import { useRef, useEffect, useState } from "react"
import { createContainer } from "unstated-next"
import { createSocket } from "./utils/sockets"
export function useSocket(url) {
let socket = useRef(null)
useEffect(() => {
socket.current = createSocket(url)
return socket.current.connect()
}, [url])
return socket.current
}
export function createSocketContainer(path) {
return createContainer(() => useSocket(url))
}
export function useSocketMessages(Container) {
let socket = Container.useContainer()
let [messages, setMessages] = useState(socket.getMessages())
let onMessage = () => setMessages(socket.getMessages())
useEffect(() => socket.onMessage(onMessage))
return messages
}
Step 3: Using it in your app
Then its just a matter of using those hooks and context in your app:
import React from "react"
import { createSocketContainer, useSocketMessages } from "./hooks/sockets"
let Notifications = createSocketContainer("/notifications")
let Posts = createSocketContainer("/posts")
function NotificationsList() {
let posts = useSocketMessages(Notifications)
return <div>{posts.map(post => { ... })}</div>
}
function PostsList() {
let posts = useSocketMessages(Posts)
return <div>{posts.map(post => { ... })}</div>
}
function App() {
return (
<PostsSocketContext.Provider>
<NotificationsSocketContext.Provider>
<NotificationsList/>
<PostsList/>
</NotificationsSocketContext.Provider>
</PostsSocketContext.Provider>
)
}
Step 4. (Optional) Publish your api/hooks
If you break this down into concrete steps and make sure that at each level,
your code is reusable. Go ahead an publish it as an npm package and contribute
back to the community.
from unstated-next.
Thanks! Sorry, I misspoke. I meant websockets.
from unstated-next.
The example is much appreciated, just a couple followup questions:
-
Would it be possible to have particular messages modify the state used in other hooks? This is where redux tends to shine, I can take that message and turn it into a state update for things that are cached.
-
If I wanted to "log out", and have that clear out other caches from other hooks, would that be possible with this state model?
Sorry for the barrage of questions, just really a fan of this model and want to know if it's possible to scale for large applications.
from unstated-next.
- Yeah, you can either derive that state from
useSocketMessages
or subscribe to the socket and change state only when needed - This is a little bit more dependent on how you want to architect your app. You have a lot of options:
- You can add an API to reset the messages in the
createSocket()
and update the API so consumers of if always have the current state even when emptied - You can keep the Provider only in scope of a logged in component tree, and when you log out and transition into a non-logged in component tree the socket can be dereferenced and garbage collected
- You could build a whole caching mechanism to store the data that's already there and only grab the parts that are necessary
- You could use third party packages that do this for you and just follow their recommendations
- There are probably other options I haven't thought of/aren't clever enough to come up with. Feel free to experiment, but make sure you can test what you are doing, and that you can rip it out later if you don't like it
from unstated-next.
I'm going to close this as answered. Feel free to continue the discussion
from unstated-next.
Related Issues (20)
- Use a published library - Error: Component must be wrapped with <Container.Provider> HOT 1
- Translate to Portuguese
- Important React.memo tip
- Can selectors be supported? HOT 4
- Unstated-next with Next.js and SSR HOT 1
- Can I use unstated-next to store non-serializable data? HOT 1
- TypeError: useHook is not a function with Next.js HOT 1
- Reusable functions that leverage Containers outside components HOT 1
- Error: Component must be wrapped with <Container.Provider> HOT 9
- Interdependent containers and asynchronous operations HOT 3
- Can't compose containers manually? HOT 6
- Could you add something so that you can use the provider and the context in the same component? Maybe add an HOC like withContainer()? HOT 3
- Ideas for covering more use cases HOT 1
- all containers on the top level of my react application
- Why Unstated? HOT 2
- How to produce types for Containers?
- Testing UI using unstated-next
- [Question] How to use addEventListener in unstated-next
- Reducing re-renders useCallback optimization should use functional updates
- Container.useContainer() vs useContainer(Container)
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from unstated-next.