Code Monkey home page Code Monkey logo

Comments (5)

Wenqer avatar Wenqer commented on May 26, 2024 1

@rileyatodd that solution will work, but you will have problems when you decide to stop render {count} value into DOM and still updates it in the document.title.

@blacktaxi react hooks allow us to use a simpler solution then HOC:

function useSubscriptionTo(obs: Observable<unknown>): void {
  React.useEffect(
    () => {
      const subs = obs.subscribe()
      return () => subs.unsubscribe()
    },
    [obs]
  )
}
const setTitle = count => document.title = `You clicked ${count} times`

const Counter = () => {
  useSubscriptionTo(count.pipe(tap(setTitle)))

  return <F.p>You clicked {count} times</F.p>
}

from focal.

blacktaxi avatar blacktaxi commented on May 26, 2024

For this particular example, I think it would be better to just use an F.div like this:

import { F } from '@grammarly/focal'

// ...

const Counter = () => {
  const count = store.count

  return (
    <F.div>Count: {count}</F.div>
  )
}

I would appreciate if you could provide some other examples so I could get a sense of what kind of problem you are having.

from focal.

teevik avatar teevik commented on May 26, 2024

I guess I'm not really having any problems, just like the way hooks look 😅

But one use case could be using the result from useAtom in another hook, for example for updating the page title like they do at https://reactjs.org/docs/hooks-effect.html

import React from "react"
import { Atom, useAtom } from "@grammarly/focal"

// ...

const Counter = () => {
  const count = useAtom(count)
  
  useEffect(() => {
    document.title = `You clicked ${count} times`
  }, [count])

  return <p>You clicked {count} times</p>
}

(although that's probably a terrible use case)

from focal.

blacktaxi avatar blacktaxi commented on May 26, 2024

That's actually a pretty good use case, although not very common. There is an easy way to do this kind of thing just by subscribing to the atom observable:

count.subscribe(x => {
  document.title = `You clicked ${x} times`
})

The problem with this is that there's no clean up – we never unsubscribe from the observable. You can deal with this by having a special component that will manage the lifecycle of the side effect subscription. It's quite simple and could look like this:

class WithEffect extends React.Component<{ effect: () => Subscription }> {
  private _sub: Subscription | null = null

  private _unsubscribe() {
    if (this._sub) {
      this._sub.unsubscribe()
      this._sub = null
    }
  }

  componentDidMount() {
    if (this.props.effect) {
      this._sub = this.props.effect()
    }
  }

  componentDidUpdate() {
    if (this.props.effect) {
      this._unsubscribe()
      this._sub = this.props.effect()
    }
  }

  componentWillUnmount() {
    this._unsubscribe()
  }

  render() {
    return React.Children.only(this.props.children)
  }
}

// ...

const Counter = () =>
  <WithEffect effect={() => count.subscribe(x => `You clicked ${x} times`)}>
    <F.p>You clicked {count} times</F.p>
  </WithEffect>

Unfortunately this kind of utility component is not currently included in Focal.

from focal.

rileyatodd avatar rileyatodd commented on May 26, 2024

I think you could avoid managing the subscription yourself by leveraging the tap operator for the side effect.

const setTitle = count => document.title = `You clicked ${count} times`

const Counter = () =>
  <F.p>You clicked {count.pipe(tap(setTitle))} times</F.p>

from focal.

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.