Git Product home page Git Product logo

Comments (5)

jamiebuilds avatar jamiebuilds commented on May 30, 2024 3

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.

mattoni avatar mattoni commented on May 30, 2024

Thanks! Sorry, I misspoke. I meant websockets.

from unstated-next.

mattoni avatar mattoni commented on May 30, 2024

The example is much appreciated, just a couple followup questions:

  1. 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.

  2. 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.

jamiebuilds avatar jamiebuilds commented on May 30, 2024
  1. Yeah, you can either derive that state from useSocketMessages or subscribe to the socket and change state only when needed
  2. 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.

jamiebuilds avatar jamiebuilds commented on May 30, 2024

I'm going to close this as answered. Feel free to continue the discussion

from unstated-next.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.