grammarly/focal

[Questions] React Ecosystem Support: CRA & React Native?

loganpowell opened this issue · 15 comments

Hi!

I'm seriously considering using Focal, but couldn't find docs to answer two of our higher-priorities:

  1. I noticed the <F.div> component looks like a pretty serious investment of time for your team to have produced. I couldn't find an analog for React native in your repo anywhere and assume you aren't currently using Focal with React Native. Am I mistaken? If not, have you any plans to create an observer <F.view> or the like?
  2. Would I be able to customize a create-react-app to leverage Focal or is it currently just "clone" and figure it out? Just curious.

Thank you for the documentation! It's very concise! I'm very excited to see movement in this area!

Hi, thanks for your interest!

  1. We are not using React Native right now and I don't really know much about it. All of the F.* components share the implementation with liftIntrinsic function (same as lift but slightly differently typed), see here. If React Native component lifecycle is the same as React.js (which I'm not sure about), it should be possible to create F-style React Native components with either lift or liftIntrinsic. I'd appreciate you sharing any findings on this would you ever try it :)
  2. I believe you don't need to customize create-react-app to use Focal, unless you want it to come bundled. Focal can be used with just a library import, and there is no need to change your build infrastructure. We've only used Focal with TypeScript so far, but I think it should work the same in a JS app.

Thank you for the quick and thoughtful response @blacktaxi

I'd appreciate you sharing any findings on this would you ever try it :)

I haven't yet tried it of course, but here's the list of react-natives intrinsic components:

https://github.com/facebook/react-native/tree/26684cf3adf4094eb6c405d345a75bf8c7c0bf88/Libraries/Components

Do you think it would be a pretty straight-forward port using Focal's lift functions?

Also, it seems calmm experimented with this concept:

https://github.com/calmm-js/kefir.react.native

relevant chat on gitter

Sorry for being a pest, but I have another question. Could I use Focal for everything except <F.div> and instead use recomposes observable utilities?

Here is the implementation:
https://github.com/acdlite/recompose/blob/master/src/packages/recompose/componentFromStream.js

Hey @loganpowell, I checked out componentFromStream and it seems to be very similar to what Focal does if I understood it correctly. I don't see an explicit reason why you wouldn't be able to use Focal together with recompose. componentFromStream seems to create a React component, and so do <F.*> components from Focal. So I would expect to be able to use them side by side, and compose too.

I would appreciate if you could report your experience with this would you ever try it!

Re: React Native. I think you can just try lift-ing React Native components and see if it works?

I would appreciate if you could report your experience with this would you ever try it!

I would really like to try! I am not familiar with Typescript. Do you have any docs for those of us in regular JS land?

Oh, that's a good point. Unfortunately there are no real JS docs at the moment. But it should work the same if you just drop type annotations. Here's an example for a counter in JS, if it's of any help: https://codesandbox.io/s/qv7kmm19w.

import React from 'react';
import {F, Atom} from '@grammarly/focal';

const Counter = props => <F.div>
  {/* use observable state directly in JSX */}
  You have clicked this button {props.count} time(s).

  <button
      onClick={() =>
        // update the counter state on click
        props.count.modify(x => x + 1)
      }
    >
      Click again?
  </button>
</F.div>

// create the app state atom
const state = Atom.create({ count: 0 })

// track any changes to the app's state and log them to console
state.subscribe(x => {
  console.log(`New app state: ${JSON.stringify(x)}`)
})

export default ({ name }) => <div>
  <h1>Hello {name}, here's a counter!</h1>
  <Counter count={state.lens('count')} />
</div>

Thank you for this. I will give it a go this week. One last question (for now): Can I use any lens library to work with the focal atom (e.g., ramda or partial.lenses)? I couldn't find any notes in the docs/readme about library interop.

Cool, let me know how it goes!

I haven't really researched this, but I don't believe Focal lenses are going to be compatible with other libraries, at least not right away. They definitely will not be compatible with ramda or partial.lenses as they use a different representation. However if you have interest in that, I think it could be possible to convert between them in many cases, without a lot of complexity.

Ok, first report:

https://codesandbox.io/s/lplpqw3yoq

At first blush, seems promising. I will continue to journey down this path to see how far it can take me.

Cool. I'm not sure I entirely understand what it does though :) But it seems that Observable.from(count) is unnecessary – Atom values are already observable, so that's unnecessary. I tried removing it and it seems that it's still working.

Hey @loganpowell – just checking in. Did it end up working out for you? Care to share your experience?

So sorry for the delayed response on this. In my typical (ADHD) fashion, I've gone down a tangential path to solving this... Clojurescript (Reagent/Re-frame).

Ok, that's cool, thanks for the heads up!