From personal experience, I've had great success targeting the 3 platforms you mention in a single RN codebase, with a very high degree of code re-use.
This isn't really accurate. Presuming you're using react-native-web [1] (the most popular version of RN targeting the web, although there are others), it's essentially just a set of components and APIs, fulfilling RN's API, which sit on top of React DOM.
So anything you could do in React, you can also do in RNWeb, as it's a superset of React.
Of course, you'd need to use the RN components if you want to share code between web and native mobile. But there's nothing stopping you reaching a high degree of code re-use, and/or using React components for the web-only portion of a RNWeb project.
I've been designing and building apps and web platforms for the last 10+ years, currently freelancing with a small team. Lots of experience helping startups launch future-proof MVPs, and happy to offer any level of assistance across the whole product spectrum (from UX, to marketing, to business strategy..).
Frontend focus is React/React Native, as it's allowed us to target all 3 platforms (web, iOS, Android) with unprecedented efficiency.
Yeah I realise you'd never reach the same level of soundness due to the limitations of the underlying JS (although presumably you could get close with a subset?). But that's why it's an interesting challenge, and I think what Flow has shown is that it's possible to get a lot closer than had previously been imagined.
If everyone just accepted the argument 4 years ago that "JS will never be sound" then maybe today TS would still just be Java style `interface` annotations for classes. It's not like the Flow team has reached a ceiling at this point... there's still plenty on their roadmap that would continue to improve soundness and expressiveness.
> You can’t have anything approaching ocaml correctness when in typescript all objects with the same shape are interchangeable.
Could you elaborate? Flow has recently switched to exact objects by default[1], which I would have thought would be enough for a sound approach?
Something which I think could be helpful for the overall ecosystem, and allow both type systems to coexist and thrive, would be more attention put into tools which transpile code and type definitions between the two languages. The two most popular projects that I could find[1][2] are unfortunately incomplete and have not received any real updates in months.
So, I was one of (or I suppose the only...) person in the linked issue arguing that competition is useful, and that it makes sense for Facebook's products to be tied into the same ecosystem.
As others have mentioned, when Flow was first launched, TS had an extremely limited type system (e.g. no null checking, no union types). Of course this has improved a lot over time, as the two have converged, but there's still a long way to go for either project to allow JS reach the level of correctness and expressiveness of, say, OCaml or Haskell.
Flow has consistently for the past few years been bringing new ideas to the table from this algebraic data types background, which often have ended up proving to be good ideas, and are in various stages of trickling down to TS.
I worry that if the ecosystem becomes completely dominated by TS, the overall focus will end up back where TS started: rudimentary OOP inspired types, without the underlying goal of overall correctness, which Flow strives for, while TS openly eschews in favour of "pragmatism".
Depending on your stack it might be possible to make use of it already, e.g. Babel has a transpilation plugin, and Flow supports it for static type-checking.
As Dan said when closing that issue, this seems to me how I would expect rendering in React to work... it's async by nature.
If you need the component's state/props to be a certain way for the very first render, use `this.state = {...}` in the contructor, or wait until the Redux store is in the correct shape before mounting the component. (I'm guessing this is what you've done in your HOC, so this sounds like the right solution to me).
Calls like `dispatch` and `setState` shouldn't be expected to reflect in a component's rendering synchronously. And as far as I know, as of Fiber, componentWillMount is even going to become a method that could be called multiple times before the component actually mounts... its usage is pretty widely discouraged for most cases: https://github.com/facebook/react/issues/7671
Why use componentWillMount and not componentDidMount? From the docs:
> componentWillMount() is invoked immediately before mounting occurs. It is called before render(), therefore setting state synchronously in this method will not trigger a re-rendering. Avoid introducing any side-effects or subscriptions in this method.
> componentDidMount() is invoked immediately after a component is mounted. Initialization that requires DOM nodes should go here. If you need to load data from a remote endpoint, this is a good place to instantiate the network request. Setting state in this method will trigger a re-rendering.
> Option 1: Use a string or null/false data [...] If you're using a type checker like #flow, it will yell at you and for a good reason: data type changes are hard to reason about and very error prone in practice.
This isn't true. Flow is great at enforcing that all potential types/values are handled in an if statement. If the following type was used, the code missing the failure case would have been picked up by Flow:
type Pics = 'fetching' | 'failed' | Array<Pic>
> Option 2: use an object with two props [...] someone accidentally changes the status without changing the data. Or the other way around. This will result in nasty and hard to debug issues where the state and data don't match visually.
Again, this can be avoided by using the correct union in Flow, which will pick up right away if the two properties have become inconsistent:
I'd highly recommend using a type system like Flow to enumerate the shape of possible actions the store should support. This brings numerous advantages:
1. You can use strings for action types, no more need to import constants.
2. No need for action creators for simple actions, you can just create the action object inline and Flow will validate its shape.
3. You can be sure that reducers are unpacking properties that actually exist from the actions.
In other words, your example could simply be:
// types.js
type Action =
| { type: 'ADD_TODO', text: string }
// TodoList.js
dispatch({ type: 'ADD_TODO', text })
...and Flow would confirm at 'compile time' that it matches the contract dispatch expects.
This approach has scaled up extremely well for me and no longer feels verbose.
It isn't multi-user, but does introduce features around tying tasks to larger goals, progress tracking etc. It's also currently just a web app, but at the moment I'm working on native iOS/Android apps.
Something this article glosses over is that JavaScript achieved all the benefits of ES6, ES7, gradual typing, etc, without breaking backwards compatibility. I can still pull in a library written 10 years ago alongside my fancy new async/await code.
Perhaps this can be partly credited to JS's decision to go with a more minimal standard library, meaning it didn't end up with the Python 2/3 situation as standards evolved.
React Native is primarily aimed at writing cross-platform UI code. When it comes to performance critical code, or integrating heavily with native UIs (eg the media streaming abilities of Spotify) it's perfectly fine to drop down to native code. RN provides an easy way to bridge between the JS and these native components.
Nope, sorry, I'm fully focused on the SaaS model. If it helps at all, I've tried to remove as many concerns as I can associated with storing these kind of things in something cloud-based. See the list of pledges on the homepage, and the privacy policy.
Thanks! Not at the moment. It would be nice to one day, but given that I'm bootstrapping, the rate of growth is quite slow, and I don't think it's reached the scale yet where it would make sense to do full-time.
For anything which I can't figure out a way to tie to one of my current goals, a helpful general rule of thumb is that, it may not actually be that important to hold on to. There are of course exceptions, but they're few enough that a nice folder structure on my hard drive can catch the rest.
I've been using Pinboard for a while as a bookmark list, but find the lack of any structure beyond tags a bit limiting. Just feels like I'm dumping links for the sake of it and will never really end up referring to them again.
I approached this problem and decided to try and solve it for myself just over a year ago. Firstly, I decided that instead of knowledge being segregated by medium (notes -> evernote, bookmarks -> Chrome, etc), it should be organised by purpose.
The most important purpose, I decided, was personal goals. Knowledge/information which is relevant to helping me achieve my own goals is the most important thing I should be focusing on, and should be extremely well organised and easily accessible. Any other interesting info that falls outside that is a bit of a shame to lose, but ultimately just a distraction and clutter. For this purpose, I developed this tool: https://nachapp.com
I believe the next level of information down would be general learning/knowledge. Stuff that doesn't fall under any specific goals, but is still useful information to know and understand (and may in disparate ways tie into core goals). For this, I'm currently using https://pinboard.in, although it's not ideal as it's again limited to a single medium. I have a solution in mind, but haven't started developing yet. If you're interested, feel free to get in touch and I can keep you updated (contact info in profile).
From personal experience, I've had great success targeting the 3 platforms you mention in a single RN codebase, with a very high degree of code re-use.