artsy / artsy.github.io

The Artsy Engineering Open-Source Developers Blog
https://artsy.github.io
MIT License
1.08k stars 227 forks source link

Comments: React Native for an iOS Developer #362

Open orta opened 7 years ago

orta commented 7 years ago

React Native is a new native library that vastly changes the way in which you can create applications. The majority of the information and tutorials on the subject come from the angle of "you are a web developer, and want to do native".

This makes sense, given that the size of the JavaScript/web audience is much bigger than native developers, and far more open in the idea of writing apps using JavaScript. For web developers it opens a new creative space to work, however for native developers it provides a way to work with different tools on the same problem. Considering that most developers with a few years on the platform will be comfortable with the Xcode toolset, recommending a change this drastic is a tough sell.

We've been using React Native now for about a year and a half, and have started to slow down on sweeping changes inside the codebase. This is great because it means we're spending less time trying to get things to work, and more time building on top of a solid foundations. Now that we're settled, it's time to start deeply understanding what happens with React Native.

Link: https://artsy.github.io/blog/2017/07/06/React-Native-for-iOS-devs/

keitaito commented 7 years ago

Hi Artsy team,

First of all, thank you for the post "Intro to React Native for an iOS Developer". I wanted to try React Native, but I was hesitated to get started for some reason. But this blog post is very encouraging, and I finally has got started to learn it.

I just wanted to let you know I had a small issue when I installed react-native-cli. After installing it by yarn global add react-native-cli (yarn was installed via Homebrew), react-native command was not found. It was because the $PATH to yarn global bin was not configured. This issue was reported at the yarn repo issue page. So, I updated my .bash_profile by adding export PATH="$(yarn global bin):$PATH", and re-loaded it. Now react-native command can be found successfully. Maybe someone else might have got the same issue, so I thought this could be helpful for them. Thanks!

orta commented 7 years ago

Thanks @keitaito - I've updated the post to mention your comment, and if anyone has just come down here for that, you can click this link to get back to where you were.

s4cha commented 7 years ago

Such an insightful post ! Thanks for sharing that experience with us :)

proactive-solutions commented 7 years ago

Hi Orta, Thanks for such a detailed post. What's your view on code injection and swift playground.

Also KickStarter is using kotlin and swift along with reactive framework such as RxJava and RxSwift, so both Android and ios teams can share the same ideas.

How you think about that approach?

orta commented 7 years ago

What's your view on code injection and swift playground?

Injection4Xcode is what made native iOS development continue to work for me, I covered the ideas in this post and the technical aspects in this one. Long story short, code injection can only be done by Apple in Xcode. I've filed the radars etc, and it'll be a pleasant surprise if it comes. It's a fine hack today, but there are lots of places where Injection doesn't work.

Playgrounds are a nice tool, and Kickstarter are doing some really interesting work on UIViewControllers in playgrounds. I've found Playgrounds to be a great teaching abstraction, but I struggled to find other use-cases for them, and eventually stopped trying.

[...] Reactive framework such as RxJava and RxSwift, so both Android and ios teams can share the same ideas.

Reactive programming is interesting, I've worked on 2 (Eigen/Eidolon) apps using reactive paradigms now. I think RxSwift is a great move towards being able to talking with the same ideas across platforms. We don't have an android app at Artsy though, so the other team we try to share with is web. React Native gave us the ability to share the exact idea instead of re-implementing across platforms.

If/when we start an Android team, we don't need three implementations (android/ios/web), three languages, three Rx implementations, and three different toolchains to build one feature. We can work in a shared context with similar tools and the same mind-set.

It's a different trade-off, but companies like Kickstarter are great examples of apps which would get a lot of value from using React Native.

irfanahmadein commented 7 years ago

wow, thanks @orta for such a detailed post on your journey towards React especially for an iOS developer πŸ‘

DwarDoh commented 7 years ago

Very nice write up. Refreshing perspective after being a native developer my entire career. The world of the web is not my comfort zone. I wish I had read something like this a few months back when I started a fresh iOS project based on an isomorphic JS framework of my own. I ended up writing a Swift version because I wanted the highest quality, at the expense of some isomorphism. I think RN could have done the trick.

However, after that experience I want to return to the JS version and catch it up to what I've done in iOS, and maybe even supplant both with React and RN re-writes. I would need the following from RN. If anyone would care to comment I would be very grateful. As a disclaimer, I don't know many details about RN coding.

1) Size and position a component wrt its parent, relatively or absolutely.

2) Compose a Component's render() function at run time.

In my platform the view hierarchy is specified by a runtime loaded orchestration json. The JSX code doesn't appear to permit that at first glance, the pure JS may work.

3) Handle a variety of gestures, currently swipe (all directions), pan and tap (multi-touch). Does something like hammer.js play nice with RN? Does it have it's own gesture support?

4) Animations for view transitions, and other effects, think bounces. I think what you mention in the article will cover these needs. Comments?

5) Leverage a responder-like event chain in the view hierarchy. i.e. children pass unhandled events/gestures up the view tree.

6) I hesitate to use RN because I would lose additional isomorphism, with the web version, which I'd probably re-write as React-based, to preserve as much iso as possible.

Why didn't RN just use DIV components instead of introducing VIEWs? Seems a shame. Perhaps there is a RN effort to provide a library enabling web support? Thoughts?

===

For completeness, my current JS platform utilizes the UI framework famo.us, which has gone dark. famo.us did provide all the above and presented a purely JS centric dev experience, much like native dev.

orta commented 7 years ago

OK, that's a lot of questions πŸ‘―β€β™‚οΈ

Size and position a component wrt its parent, relatively or absolutely.

React Native supports both flex box layout (for relative) and absolute positioning with TBLR style.

Compose a Component's render() function at run time. + In my platform the view hierarchy is specified by a runtime loaded orchestration json. The JSX code doesn't appear to permit that at first glance, the pure JS may work.

In this case JSX does support this, for example:

  render() {
    return (
      <View>
        <SearchQueryInput text={{ value: props.query }} ... />
    [...]

Will set the text at runtime to be the object { value: props.query }, JSX at transpile-time is only replacing <SearchQueryInput text={{ value: props.query }} ... /> with React.createElement('SearchQueryInput', { text: { value: props.query}}).

Handle a variety of gestures, currently swipe (all directions), pan and tap (multi-touch). Does something like hammer.js play nice with RN? Does it have it's own gesture support? + Leverage a responder-like event chain in the view hierarchy. i.e. children pass unhandled events/gestures up the view tree.

RN has a responder-chain like event support - as it supports Android it doesn't have all UIGestureResponder subclasses - but pan is there. WRT a pretty complex multi-touch UIViews, I think you'll really need to be doing that sort of stuff inside native code which can be wrapped with data from the React component props.

Animations for view transitions, and other effects, think bounces. I think what you mention in the article will cover these needs. Comments?

We've not had to dig too far into it other than our pretty simple use-cases. I think the baseline support is pretty good - you can choose the level of support you want ( e.g. Lottie or Animated)

I hesitate to use RN because I would lose additional isomorphism, with the web version, which I'd probably re-write as React-based, to preserve as much iso as possible.

We're slowly looking at isomorphic code, today we've not done anything other than keep our web and mobile React projects at tooling parity. I know that Airbnb and at least one or two medium-sized companies who haven't talked about it yet are going all-in WRT a single codebase for them both.

It's feasible, it's just a bit unknown what the trade-offs are so far. We've not had project in Artsy that needed it though, so it's a bit hard to say how well that works out.

Why didn't RN just use DIV components instead of introducing VIEWs? Seems a shame. Perhaps there is a RN effort to provide a library enabling web support? Thoughts?

Re: div instead of view, I think FB fell down on the side of view is a better description of the thing you're working on when it's empty. It also makes it feel right in VR, Android and iOS. Plus whatever platforms they make in the future.

WRT cross-platform code, there's react-primitives which aims to provide the root elements for all platforms. It's the basis of react-native-web and react-native-sketch. That's where you want to keep an eye on if you're looking at isomorphic code.

proactive-solutions commented 7 years ago

I am working on React Native project for past 2 months and IMHO React Native is for those who are willing to spend lots of time configuring things an finding out the compatible modules.

If you have very good knowledge of JS then it might work for you

My observation is RN is not a silver bullet to all your problems. It is just another option to develop your app like Xamarin, Titanium and all other cross platform tools.

DwarDoh commented 7 years ago

Thanks @orta for your detailed response. Very helpful!

JuniusAng commented 7 years ago

Hi @orta great insight! btw:

When React Native was proposed as an option for us, the majority of our mobile dev team were not exactly excited at the prospect of using it

I am curious about this, is your mobile team still hesitating for react native? i think i can gladly use some argument. been struggling with that πŸ˜„

orta commented 7 years ago

I am curious about this, is your mobile team still hesitating for react native? i think i can gladly use some argument. been struggling with thatΒ πŸ˜„

Nope, everyone has touched our React Native side of the app now, @ashfurrow was the last holdout and once you have wrote a feature in React Native vs doing it native you don't go back easily. This tweet basically sums up how our our Emission/Reaction) strategy has been affecting teams that work inside that environment.

pavelosipov commented 7 years ago

Thanks @orta for a great post! I'm curious how RN fits for the applications with very complex layout for collections. Is it possible to write a bridge for UICollectionView with custom UICollectionViewLayout and fill it with data on JS side?

orta commented 7 years ago

It's possible, but probably isn't a great idea if you think the data is going to change inside it.

Just like there's no direct map for a UITableView, there's no direct map for UICollectionView in React Native and trying to force the two to co-exist means one side is going to have to give up control. However, you can treat your UICollectionView as a dumb view, then you could wrap it into JS. We initially tried this with our masonry/pintrest views in the app, and once we started adding pagination it just became unweidly and we moved to pure React.

pavelosipov commented 7 years ago

Do your phrases like "dumb view" and "give up control" mean that UICollectionView should be implemented and populated on the native side and the only responsibility of JS side is to specify its position on the parent's view?

orta commented 7 years ago

Yep, I'd say that's the best option there.

DerekSelander commented 7 years ago

Hi @orta, was wondering what your mobile team size was before adopting React Native. Also, how many devs do you have working on React-Native related repos nowadays? Thanks

orta commented 7 years ago

Hey there Derek, we adopted React Native when we were a team of 5 people - we've been that size for over a year and a half. We're roughly split 4.5 - 0.5 on two apps, and two of us are manager-y types that don't work full time on code that is just the React Native codebase.

I think it's reasonable to say we have 3-4 people in constant dev on our React Native project. There are currently 7 open PRs from 4 people, and in the last month we've had PRs from 8 people. With the others coming from web and API backgrounds.

oferRounds commented 7 years ago

Great article – THANK YOU!

One question please: I’m using RN + Typescript. I’m now trying to include a static image while following the relevant documentation, but keep getting the error:

"Unable to resolve module `../assets/images/googleIcon.png` from `<Project_Path>/artifacts/components/LoginForm.js`: could not resolve `<Project_Path>/artifacts/assets/images/googleIcon.png' as a file nor as a folder"

Any idea how solve this?

Thanks again!

orta commented 7 years ago

Hi @oferRounds - that's something you should be asking on Stack Overflow πŸ‘ - it shouldn't be any different in TypeScript. You can go see how we do it inside Emission's source code for references also.

oferRounds commented 7 years ago

@orta - got you, thank you for your reply!

lsolniczek commented 6 years ago

Hi @orta In my company we have two team and two apps: one for iOS and one for Android. I was thinking about using RN as view part in both applications. We want to stick with Swift and Kotlin in logic. Is it posible to define one interface to communicate between RN and Native, write implementation in native code and use it in View out of the box, for both platforms, or we will need something more?

orta commented 6 years ago

I think if you consider the entire screen to be a React Native view, then this technique can work. πŸ‘

When you create a React Native view, you pass in a dictionary with the top level props for the React component tree. You can generate that dictionary entirely in native code, and then pass it in to React. You can write tests on the native side that the output is always shaped correctly, then make the assumption that it's going to be correct inside you JS.