Building a social network app with over 100K users 100% in React Native — Sharing Best Practices, Performance Optimizations, and Practical Experience


(Adam Terlson) #1

In this talk, I share the experience we have gained building iOS and Android apps using React Native for over 100K global users. The talk contains best practices, tips, tools, code sample demos, and a whole ton of opinions.

I’d be happy to answer any questions you may have in the comments!

If you know of any community who might like to hear this talk live (I live in Munich, Germany), please get in touch!


(Adam Skinner) #2

I really enjoyed this presentation and actually put the { ids, byId, byComposite } idea into play recently.


(Adam Terlson) #3

I’m happy to hear you enjoyed my talk! When you say “byComposite,” this is a “pre-computed index” sort of lookup table? Or what do you mean “byComposite”?


(Adam Skinner) #4

Yeah. When I say byComposite, I mean an object whose keys are composed from properties of the object. Like identifying a row in the database by a composite key rather than a unique id.

eg { id: 1, itemType: 'a', itemId: '234' } gets popped on as { "a 234": 1 } or if multiples meet the “query” represented by the key, an array of ids.


(Adam Skinner) #5

While I don’t have any smooth generic methods yet like you do, here’s how I implemented the idea in my reducer for comments:

  const getCompositeKey = c => `${c.ItemType} ${c.ItemId}`;

  if (action.type === COMMENTS_RECEIVED) {
    const ids = map(action.data, 'Id');
    const byId = keyBy(action.data, 'Id');
    const compositeItems = groupBy(action.data, getCompositeKey);
    const byItem = transform(compositeItems, (result, value, key) => {
      result[key] = map(value, c => c.Id); // eslint-disable-line no-param-reassign
      return result;
    });
    return {
      ids: union(state.ids, ids),
      byId: merge(state.byId, byId),
      byItem,
    };
  }

(Eduardo Rabelo) #6

great talk @adamterlson, thanks for sharing your experience!

i liked the way you used race as control flow for cancelling the worker when the device is on/off!

:hugs:


(Adam Terlson) #7

@oieduardorabelo I made my saga demo into a “lightning talk”, and you can view that here: https://www.youtube.com/watch?v=Pg7LgW3TL7A

Please share with others you think might find it interesting. :slight_smile:


(Adam Terlson) #8

@demoran23 Yup, looks very similar! Nice. :slight_smile:

By the way, it looks like you’re looping through your state/action.data structure multiple times: during groupBy, transform and during merge. Not sure how big your data structures are, but you could consider using mergeWith instead to avoid that.

Thanks for sharing!


(Jonathan Wheat) #9

This was great, thanks for posting it. I’m a little past just starting out, and I learned about so many new tools and techniques to look further into. I was scribbling notes the entire time. Can’t remember the last time I took notes watching you tube :smile: :+1:

I have not used React (for web) at all, and jumped straight into React Native (coming from Appcelerator / Titanium). Do you have a background in React and if so, did that help you in any way with React Native? Would you recommend any special skills to brush up on jumping straight into React Native?

Thanks again for the video


(Adam Terlson) #10

Hey there, sorry for my late reply. I’m so happy that you enjoyed my talk, it means a lot to me. Thank you!

Like you, I had no prior experience in React before building with React Native. I would dare to say that React Native will actually make you better at React than it would to start the other way around. Some limitations might be that you don’t always get the latest React features in RN and have to wait, but the advantage of working with React Native is that it forces you focus on the fundamentals more.

For example, I think that RN gets you out of the mindset of seeing JSX as HTML. I developed a thought pattern of JSX as a JavaScript extension, instead of JSX as a template language, because I started with React Native. Single-purpose, reusable stateless functional components (which are idiomatic) are easily achievable in the simpler UI case of RN. Higher order components, while they may be hard to find use for on the web, the often-repeated UI patterns of content-based mobile apps make HOCs a natural fit (though render props are definitely also worth considering).

Anyway, you’re in the same boat as I was starting out, and I would say that will make you better at React over all. Soon you’ll consider React on the web to be rather boring. :slight_smile:


(Luis Del Giudice) #11

Great talk loved it @adamterlson I have a few questions for you would appreciate if you can reply:

  1. What opinions do you have on the way you structure code, as in how actions, apis, presentational, hoc, containers are laid out in the filesystem.

  2. In your case you started with a big app, what happens if I actually have a small app but eventually I want it to scale. Do I have to start with all these fancy sagas and redux utils


(Adam Terlson) #12

Thanks for the questions, @delgiudices, and I’m glad you enjoyed the talk! I’ll do my best to answer.

  1. The question is a bit vague. In general, I think a big difference between building on the web and building in mobile is that your data and business logic in a mobile app are “centralized” where on the web they are often coupled with the page that you’re on. I think the way we organize our code reflects this: three, single-responsibility modules (data store, UI, business logic). This pattern is tried-and-true, and reflects a standard 3-tier application structure. Each module is logically independent, and “owns” the actions it watches, while importing actions from other modules as required. So the ui module may import * as apiActions from '/app/saga/api/actions' for example.

  2. Do you “hope” it will scale, or do you “know” you will have to scale it? If you’re simply wishing for future growth, that’s a future you don’t want to make difficult, but nor should you build it up front. Your objective should be to use the best tools to fit the job you have in front of you and not try to architect for the future that may never occur. That having been said, if you’re using redux, IMO once you get over the small learning curve of Sagas, they don’t actually present any overhead in your application itself. If I were to create a simple app that just had a couple async workflows, I’d consider using saga right away. This is because, for me, Sagas is just as easy to use as thunk, and I don’t need to worry about scaling issues if the async flows get crazy. There’s a lot of personal preference, for sure, but when you’re just starting out, optimize for developer efficiency, don’t build for an unknown future.


(designer24) #13

Awesome. I like InterNations website and glad to know you guys are using React Native.


(Alec Lorraine) #14

@adamterlson I have a question I think you might be able to answer. Loved the talk (especially how detailed it was).

When a user sends or posts a message, and they close the app before the saga returns a success action, does that network request still continue and will the saga return success while the app is in the background?

My problem is- if the user sends a message and then closes the app before it’s done sending, my thunk returns a success access but the message object isnt getting created in my DB. Im not sure why. Any ideas?

Thank you!


(Adam Terlson) #15

Hey there Alec, I’m glad you enjoyed my talk!

Yes, the saga system we have in the app will in fact complete the request. However, the saga function doesn’t suspend and resume, because at some point your app will be totally stopped and its memory released, so completion isn’t possible in this way.

Instead, when you dispatch a REQUEST action to fire a network request, that action is persisted to redux (which is persisted with the help of redux-persist). When the app resumes, the first thing it does is restore persisted actions back out of state and loads them into the channel to be processed. So, it doesn’t complete the original function calls per say, but it will service the original request reliably.

I made a concise video (sourced from the longer talk) where I lay the foundation for this system: https://www.youtube.com/watch?v=Pg7LgW3TL7A

Hope this helps!


(David M) #16

Great video do you use Redux Persist along side Redux Saga?


(Adam Terlson) #17

Yup!


(Alec Lorraine) #18

Gotcha. Will start implementing that now. Thank you!


(Brent Vatne) #19

:wave:

nice work @adamterlson!


(Adam Terlson) #20

Thanks!