Hacker News new | past | comments | ask | show | jobs | submit login
Lessons learned as a React contractor (medium.com/jolyon_russ)
310 points by lxm on Jan 5, 2017 | hide | past | favorite | 168 comments



OK. Here's what I've learn after ~2 years of doing react myself.

1. Wrap third party components, so you can swap them easily if they become unstable or you find something better. 2. If you have a codebase that predates create-react-app, take a look into its configuration, webpack is a complex beast and they've figured many optimizations. 3. Learn the concept of High Order Components and use them to abstract common functionality (for example, retrieving data from an API) 4. Even if you use Redux (I do and I love it), not everything belongs in there, use local state whenever it makes sense first. 5. Never, ever, depend on anything inside `react/lib`


The more I've thought about this the more I think the first point is the best decision for every long-lived application.

Wrap _all_ third party library calls. This lets you reduce the scope of these calls to "approved" ways and make much stronger assertions about who's doing what in your code.

This gets super useful the further down the line you get to adding really complex features. Being able to isolate all the places where certain objects get created to add a permission check is nice.

It also makes testing easier because you have some nice entry points to mock.

Raw usage of things like an ORM can let you get through a prototype super quickly, but makes editing the application later on quite hard.


Yes. Definitely. I have benefited enormously from doing this in C# for a few years now. Certainly the wins in testability can be significant, but it also isolates the third-party dependency's behaviour and lets you wrap it with something that exposes the interface you actually wanted. Which you can test in isolation and be confident in.

It's a shame it's really really tedious though!


Sincere question: do you really have the feeling the over cost is worth it? Do you do this for EVERY external library you're using?


It really depends on the library. Sometimes you look at the API of a library and you just want to wrap it because you know you're going to have to do a lot of work to get the data in and out of it in the right shape, or the lifecycle management is a pain, or the types involved aren't going to play well with tests, or it's just fundamentally relying on external state, thus preventing me writing proper unit tests of anything which might call it.

Other times, no, it doesn't seem worth it. And I don't do it for every single external library I use.

Although it does tend to end up being most of them - which seems to be a consequence of the way I've generally done n-tier application design at work. I'm not always a fan of this architecture, but sometimes it does fall out nicely.


Yeah, I don't get it. Swapping out a third party library is rare and usually because you want to get extra features another library doesn't have or some other big reason. Given how rare it is I would just use the library as is and refactor if/when the time comes. If you wrapped every library you'd waste a lot of time.

I had a senior developer suggest I wrap jQuery one time.


Honestly in JavaScript there's very little call for it because the language is so flexible, and you can't really build anything that's unmockable.

C# is a very, very different matter, and that's the perspective I was initially commenting from.


No, some libraries (like React-bootstrap) export a bunch of components that don't really need a facade. But be careful. Later, when you need to modify functionality (and it can't be done via modifying the bootstrap variables via Less) it's a slight pain to retrofit.


Even so, I like to keep the imports local so I only have to change one reference to a custom-wrapped version if/when the need arises. I have a lib file to act as a manifest of components, and while most are mine, there are also some "export {Grid} from 'react-bootstrap'" type things in there.


Re: #1, this is something non-web devs learned a long time ago. I wonder why there's not more sharing of this type of best practice information. Everyone stays in their own bubble, maybe?


Even web devs learned this a long time ago. And no we are not staying in our own bubble. As you probably know web is huge and it's hard to know all best practices. Even in the language you are programming there are probably things you don't know. People learn all the time, people start learning all the time.

It feels like people have superiority complex over front-end devs and lately specifically javascript. It bothers me. What if you tell me your language of choice and every time I see it mentioned somewhere I will post some random "intellectual question" combined with stereotype that will make you feel stupid and just demotivate you a bit. Maybe I am missing something but your comment made me feel that way.

To answer your question fully; In my opinion it's because there is no single entity that owns the web. No one controls which things should be deprecated or continued, that's why it's happening much slower because big guys have to come to an agreement. Apple provides best practices for iOS, Google for Android,... MDN is a good resource but there is no official "BEST WEB PRACTICES" entity.


I feel you took my comment too personal. Is wasn't an insult to anyone.


It was a lot more difficult in the jQuery days. Requiring a script often did non-obvious things (global variables, touching the DOM, registering even listeners, etc).




No, Proxy fits better. To be a Facade, it would have to be implemented inside React to hide React internals.

Although many patterns boil down to wrappers around objects (Delegator, Proxy, Adapter, Facade, etc.), but that doesn't make them all the same, even though their UML diagrams may look almost the same. The difference is: On which side is the wrapper? Which interfaces does it provide? Which interfaces does it use? Those details depend heavily on which architectural problem you want so solve (and it should be one you actually have). The pattern then guides you through how exactly that wrapper should look like in that particular case.


Awesome response - are you able to give me an example of what you mean "wrap third party components"?

Thanks :)


I've done this in a project recently when I was trying out different third party autocomplete components.

I had my own autocomplete component that I would use wherever I needed an autocomplete, and that component would render the third party autocomplete and supply it with the props it required. When I needed to switch out which third party component I was using, I only had to change code in one place, instead of changing it everywhere I was using autocomplete.


My lessons that I would add to this:

lessons 1: there's a good chance, depending on what you are doing, that you do not need Redux - avoid it if you can. much docunentation seems to imply that it is a necessary hand in hand element of react development - not true. I have never found any situation in which I need redux.

lesson 2:' use "create-react-app", and if humanly possible, don't eject from it.


> much docunentation seems to imply that it is a necessary hand in hand element of react development

Sorry, I don't believe this is true. Redux's author himself, has explicitly written 'you might not need redux' (https://medium.com/@dan_abramov/you-might-not-need-redux-be4...), ostensibly to combat Javascript fatigue. Redux companion libraries often include similar notes as well.


> lessons 1: there's a good chance, depending on what you are doing, that you do not need Redux

I agree

> avoid it if you can

avoid using it in a project, sure, but don't avoid learning it. It definitely helped me level up as a developer.

My favorite resource for learning about redux: https://egghead.io/courses/getting-started-with-redux


On that note: I keep a big list of links to high-quality tutorials on React, Redux, and related topics, at https://github.com/markerikson/react-redux-links . Specifically intended to be a great starting point for anyone trying to learn the ecosystem, as well as a solid source of info on more advanced topics.


https://teropa.info/blog/2015/09/10/full-stack-redux-tutoria... Is my favourite because it includes testing and knowing how to test it is super useful when you are just starting out with a tool.


this was actually the first resource I used and, while it got me off the ground, I strongly prefer Dan Abramov's egghead course that I linked above. That is the path to redux enlightenment!


Is there any sane way to use Sass, Less, or PostCSS without ejecting though? Not having variables available in your CSS seems pretty untenable for anything that has more than a handful of styled components.


Dunno really. I've never used any of the technologies mentioned and things seem to have held together OK.


You can use this fork of react-scripts which adds configuration for enabling new options, including use of style preprocessors:

https://github.com/kitze/create-react-app


The irony of forking create-react-app to add configuration.


This was the killer for create-react-app for me. I resentfully ejected so I could use SASS.


I compile the Sass files separately (using Node-Sass) and require the generated CSS file.


Not at the moment.


To further this point, don't use any library you don't need. Don't pull in Reselect until you need it (and you don't need it), Redux once you're big enough and you're passing a doTheThing() callback prop down 3+ hierarchy levels. The only "best practise" for starting is doing less, then re-evaluate when your app has too many complexities (which is the only thing more libraries will create, or solve)


If you've never used Webpack, don't use create-react-app. The configuration it generates is almost impenetrable if you're not already familiar with Webpack.


As a corollary to that I suggest people do some research into Webpack 2. Much as I like rollup's simplicity, Webpack 2 looks like it's here to stay and now that it supports tree shaking, it can replace rollup. It's worth understanding how it works even just because many tools assume the use of Webpack.

For example, Preact, which in many cases can be a drop-in replacement for React at a fraction of the size, gives instructions on how to use it with webpack (to alias react and react-dom), but not Rollup.

The Webpack 2 guides are not great, but much better than what came before, and I'm sure many blog posts will continue be written on the subject. And ultimately it's not really that difficult to get at least a decent grasp of its concepts, and it pays off in the end.


just curious, why is ejecting from create-react-app bad? some of the symlinking stuff involved with create-react-app feels unnecessary but I still value the amount of boilerplate it takes out


The point of create-reaact-app is that your build process is zero configuration.

The deepest pain point of JavaScript development is undoubtedly build configuration i.e. webpack and babel.

If you stick with create-react-app then you manage to remain in a zero build config world, which is a happy world to live in.


> The deepest pain point of JavaScript development is undoubtedly build configuration i.e. webpack and babel.

Really? Perhaps I've been doing this too long, but once you get your head round the basics I really don't think it's that bad


Is there a resource you can recommend to get your head around all the basics?


The new Webpack docs are great ([0]). Also, my React/Redux links list ([1]) has a couple sections on Webpack tutorials ([2]) and Webpack advanced techniques ([3]) like Hot Module Reloading, file chunking, and build optimization.

[0] https://webpack.js.org/

[1] https://github.com/markerikson/react-redux-links

[2] https://github.com/markerikson/react-redux-links/blob/master...

[3] https://github.com/markerikson/react-redux-links/blob/master...


Right, but even upon ejecting I still retain the ability to build/start/test with one command, the only difference is that the build/start/test scripts become static


Mostly because you can get the benefit of improvements to the build config just by updating the one `react-scripts` dependency. For example, 0.8 enabled proper sourcemaps support in Webpack (and 0.8.2 bumped the Webpack dependency to fix a problem with not being able to set breakpoints in sourcemapped code). If you eject, you don't get those easy updates, as the config files are now a permanent part of your own project.


There are a couple dealbreakers for now, but I'm seriously looking forward to the day I can migrate our stack ON to create-react-app largely for this reason. Having other people working to make my dev experience better is a huge plus.


Next.js (built on top of React and Redux, by the ppl who brought us socket.io) is a zero-config option that looks way better to me than CRA.


create-react-app doesn't support server side rendering. There are apps that don't need that- but I believe SSR should be the default, not the edge case.

create-react-app is a bundle of configuration. Configuration you'll likely need to override eventually. You're advising people new to the ecosystem blindly trust opaque configuration, and not bother understanding the underlying tools? This is terrible advice. (And if your argument is that you shouldn't use a tool without knowing how it works... Why use CRA at all? Write your own config.)


When you're at the point of needing to configure a tool which handles a base config, you need to learn the underlying tools anyway at that point, but without the experience of having built the base config up.

Keeping config directly in a project creates a maintainability issue once you have a number of projects on the go, as you then need to turn it into a module like create-react-app's react-scripts or else it's copy and paste time, which becomes horrible across multiple projects, especially if you're evolving your config as you learn.

Has anyone written a guide or supporting tools for creating your own config as a reusable module from the beginning? It feels like there's a gap which needs filled there.


> Has anyone written a guide or supporting tools for creating your own config as a reusable module from the beginning? It feels like there's a gap which needs filled there.

It looks like you did!

https://github.com/insin/ad-hoc-reckons/blob/master/Creating...


About the "go without redux point", I've switched to MobX, and it helped me greatly for this, as I can implement proper state handling very quickly even when the project is in it's infancy. You just create a class, throw @observable in it and boom, you get everything without any boiler code.


I am very confused what kind of state management MobX implements, especially after reading their current README (https://github.com/mobxjs/mobx/tree/6ed404b96a8b4074a473accd...)

Is it Ember/Vue-style "mutate, observe, compute" as implied by most of their example code or Flux-style as implied by their introduction visualization (https://github.com/mobxjs/mobx/raw/6ed404b96a8b4074a473accd2...)? Do I create actions or just mutate state directly (again, visualization and some text in the readme vs examples)? How is "observer turns React (function) components into derivations of the data they render." any different from just plain React components?

MobX feels like someone tried to make an easy state management solution (obviously a great goal) and in the process just threw together whatever pattern exist out there right now. It obviously works for many people, considering how often someone comments about it on HN, but I wonder what makes those user stick with React vs a framework that completely embraces this approach like Vue or Ember.

Is it some hard requirement on React?(EDIT: Or maybe preference of JSX?)


I second this. In my experience Mobx actually speeds up initial development. And it is easy to learn. The same cannot be said for Redux.


I used redux for a year before switching to mobx (which I've now used for more than a year). It is easier, faster, simpler, and scales better in my experience. I can't recommend it enough.


why did you do this ? we are already on redux.. but have been looking at redux with some interest.


MobX is great to get going quickly and it has good performance. However, in my experience, with a team Redux is great because it enforces a standard approach and clear representations. Well worth the boilerplate overhead.


I'm surprised there is no love for nuclear-js in this thread. I personally didn't like redux's approach, but I understand where it's coming from.

Nuclear-js feels heavy-handed, and there is indeed a lot of boiler plate, but in the end the explicit organization pays off in a huge way.

What most people don't realize is that state management will get insane past a certain point. Nuclear-JS can handle a truly massive application that is very complex -- think google docs/sheets

I imagine most people aren't building something like that though, and find it too cumbersome.


mobx looks neat ... have been using alt.js as a (similar, i think?) middle of the road solution between _all_ of redux's patterns and no flux at all..

.. i'm also told that, if all you're doing is rendering templates, you might not need anything more than hyperx (a substack production).


Here are my 2 cents:

1. Don't use a boilerplate. Not even create-react-app. Learn webpack and npm and TS / Babel. It's not that hard.

2. If you havn't yet, take a second look at MobX. I got it once I realized that I can organize my state just as I love it with Redux (normalized and update strictly through actions). With MobX you don't need Reselect.

3. Even though the React community seems to favor ES6, at least give Typescript a serious try.


>1. Don't use a boilerplate. Not even create-react-app. Learn webpack and npm and TS / Babel. It's not that hard.

I can't say that I agree with this

Hunkering down to learn build tools will probably yield the lowest ROI compared to nearly anything else you could be doing

They're nice to know, sure, but you'll pick them up along the way as you use and modify them

As you said, not that hard :)

And +1 on MobX. Bee's knees


Typescript with react is awesome and I probably would find it difficult to go back to react without it.

Getting type information in your editor when you are several levels deep in components is very useful.

My only complaint is trying to figure out how to properly work with 3rd party react modules within typescript's own namespace system


> My only complaint is trying to figure out how to properly work with 3rd party react modules within typescript's own namespace system

Could you be more specific about the issue you're having here? Might be able to help


> Even though the React community seems to favor ES6, at least give Typescript a serious try.

What's the story with dipping your toe into TypeScript on existing projects? I'm using Webpack and babel-loader, so I'm not interested in using the TypeScript compiler itself, having to renaming files to .ts, or using a different extension for files which contain JSX, but I'd still like to try TypeScript on a few modules. Is that possible?

Flow seems much easier to dip into, but I haven't tried either in anger yet.


> 3. Even though the React community seems to favor ES6, at least give Typescript a serious try.

Could you give some arguments? I'm a big ES6 fan and I can't think of a good reason to use Typescript over it.


How did you get typescript working properly with redux? I never could figure out how to get proper types in my reducers or HMR to work.


You end up doing a bit of explicit casting in places to ensure type safety, but it works. Little discussion I had about this with someone on Twitter which may or may not be relevant: https://twitter.com/tomduncalf/status/804002710878044160

I should write a blog post about Redux and Typescript - it would be good to know which bits you are struggling with.

HMR works fine with Typescript, you do need to use Babel as well though. This post I wrote should get you up and running: http://blog.tomduncalf.com/posts/setting-up-typescript-and-r..., it is a little outdated (1.9 vs 2.1) but I don't think any major changes should be needed to make it work with newer versions. Unfortunately, HMR (v3 beta) doesn't play nice with react-router as far as I can tell, so I have given up on it for now. I really miss it so I hope someone knowledgable finds time to focus on getting it working better soon!


That's a really helpful blog post, actually. I thin the general pain points are the same as in your twitter discussion - the reducers quickly start feeling clunky with explicit casts or using two lines to export a constant for the switch statement. It's obviously a possibility to just forego type-safety in that part, but it'd be a shame.

Another general pain point (apart from the fact that a lot of the guides you find seem reasonably outdated) is the general build setup. Your guide seems really good, but generally setting up react redux and typescript is a bit of a jungle.

If you do end up writing a post, please let me know!


I've not written any blog about it but I have it working in a repo [1]. The webpack config and src/model are what's most interesting for you :) To sum it up: combineReducers is templated so make an interface for your state (this is wonderful). HMR works with react-hot-loader 3 and without babel, but the documentation is lacking.

[1]: https://github.com/Zalastax/openschedule


This is nice, thanks a bunch!


I shudder at the complixity of Redux. Ooh~ nice, you dispatch an action to a reducer, ooh~. ~job security~

I don't know, it rubs me the wrong way when there are better tools out there. Mobx, is much quicker to integrate and is easier to understand how to integrate anywhere in a React app. Glad to see I'm not the only one who really doesn't like Redux.

I mean check it out, it has an incredibly small API, and even smaller if you use the right Webpack loaders.

    import { observable, observe, toJS } from 'mobx'
    export default class Store {
      @observable foo = []
    }
Then in your components just set or read from `this.context.store.foo`. Every component using the same store will update it's reference to foo.

https://sergiotapia.me/using-mobx-and-react-to-build-an-inst...


Redux is like 200 lines of code and very explicit without any magic. What exactly is complex about it?

I think too often people don't appreciate that redux, like all frameworks is a trade-off and is often the wrong tool for the job. Speaking about it as if it's a generic framework to trade out for another framework is a sign that it's being selected for the wrong reasons.

If it's not making your life easier, you probably shouldn't be using it for that application. It's a really nice framing hammer, not a multitool ;)

When I got into front end, I used redux for a small SPA with about a dozen actions and didn't really get it. "I could do this with react and basic JavaScript. Why am I writing so much extra?" I refactored redux out and it was much better.

I have another application that interfaces with a number of APIs, is a very thick client and needs to recover from local storage on startup. Redux fit like a glove!


I think a lot of the complexity comes from the incredible specificity of the docs. The authors intend to _teach_, which while great (thank you) it can seem overly complex for users who first land there.

I think a "Quick Start" section would solve a lot of the so-called "complexity" issues, showcasing a few common use-cases:

- Without React - With React

Put bare-bones code under each of those sections and then let the user learn the particulars as they come (and as their projects demand)


I'm currently the primary maintainer doing stuff with Redux docs. Right now my focus is on a tutorial series I'm writing for my own blog, but any PRs to help improve the Redux docs are absolutely appreciated!


Will give it a look tomorrow :thumbsup:


Without Redux - With Redux


I would argue that implementing it, especially in situations where you need to create a new reducer, requires a huge amount of boilerplate for something that feels like it shouldn't. Considering 75% of what you use redux for is getting and setting simple variables, I don't know why actions and reducers have to be so copy-pasty.

The core idea of Flux, and the theory behind Redux, is very simple. But I personally dislike Redux.


The boilerplate is very intentional. If you want a framework that reduces boilerplate by doing some magic or having a more strict interface, then yeah absolutely, Redux isn't the right choice for you.


>If you want a framework that reduces boilerplate by doing some magic or having a more strict interface

Having DRY code is not "magic".


It is being compared to mobx. I am not sure how observables are magical.


Have you read the source? It's far heavier than redux. Computed properties and observables that can potentially change other observables sounds like a recipe for spaghetti IMO.

@observer seems like the same thing as connect(), but it passes down the entire state as context.

¯\_(ツ)_/¯


An observable cannot change as other. If you attempt it the mobx internals will throw an error. It's been the source of finding logical errors in my code. Also the size of the lib doesn't contribute to calling it magical. Something is magical when it is complex to reason about, due to taking arbitrary seeming decisions behind the scenes.


You should read some of the comments in that codebase. (Look for the constant MAX_REACTION_ITERATIONS). I don't know why you'd paint yourself into a corner like that.

Just curious, how can you test a mobx store independently? (Sans components)


That really depends on your architecture.

The way I have it setup, everything is in a central store, and the components only access it rather than have observables for any kind of local state.

Local state is handled with boring old setState calls, so the store and data-layer is totally independent of React, and can be tested without even importing the library.

> (Look for the constant MAX_REACTION_ITERATIONS)

Okay... that's interesting. It dates back to Feb. 2016th[1], and I'm not caught up with that version. My pull comes from January [2].

Giving it a brief look over, it looks like they changed the codebase to allow for reacts to trigger themselves. My version doesn't allow that. It's a fatal error instantaneously.

Presumably, this was done to let people write recursive functions.... but I'm not 100% sure this is a good idea.

Edit: I think my version implicitly has MAX_REACTION_ITERATIONS = 1, so observables triggering itself is an immediate error.

[1] https://github.com/mobxjs/mobx/commit/a38b6a8c255d772a79dadd...

[2] I know I should update, but I come from the boring Python world where you don't expect the internals of a library to change too drastically year to year.


The only bit of Redux I actually use is `createStore`, `store.dispatch`, `store.getState` and `store.subscribe` but it seems stupidly simple to me. I sometimes start re-implementing a bit of it rather than pull a dependency in or if I am working in a language that doesn't have it as a library.

This "Redux in a nutshell" implementation might illustrate better what I mean: https://gist.github.com/MarcoWorms/30758235f05faec844b8c06ce...

React-Redux does seem to complicate things for no reason. I have just been using plain Redux with React because I didn't want to learn it.


Ah... out of curiosity, what about React-Redux seems complex?

Quick summary:

- Wrap your component tree in <Provider store={store>

- For any component that needs to access data or dispatch actions, use `connect()(MyComponent)` to create a wrapped-up version.

- Write a function known as "mapStateToProps", and pass it as the first argument to `connect()`. It will be called every time an action is dispatched, and given the latest store state. Extract whatever pieces of data this component needs, return them, and they become props for the wrapped component.

Dan Abramov wrote a miniature version of `connect` , which shows the basic approach it uses: https://gist.github.com/gaearon/1d19088790e70ac32ea636c025ba...


I guess I just don't understand the "why" so I am not motivated to look into it properly and at first glance it's introducing loads of new concepts. Maybe as my apps get more complicated I'll outgrow it but just plain Redux seems fine for me at the moment.


The hands down best reason to use react-redux is because if you use `mapStateToProps` and `mapDispatchToProps` you can keep your connected components 100% dumb (I like to export both the dumb version and the connected as the default). This way, when using something like react storybooks or and in your tests you don't have to mock your whole the redux world.


It's really not that complicated, conceptually.

Any code that wants to know when an action is dispatched needs to call `store.subscribe(someCallback)`. The `connect()` function generates wrapper components that manage that process for you, use your `mapState` callback to extract data from the store, and only re-render your "real" component when that data has changed (thanks to a _lot_ of optimization work).

Without `connect()`, you have to manage the store subscription process yourself. More code, fewer optimizations.


I introduced Redux into an app with an older version of React, and instead of updating decided to reimplement the important parts of `react-redux` as a shim. Didn't take long, and it was a satisfying education.


It rubs me the wrong way when someone uses JS instead of ClojureScript. And I bet someone could reply to me saying it rubs them the wrong way when I use that instead of Elm.

There are always going to be alternative tools out there at different timelines. Projects get started at various times when certain tools are popular, and people have varying opinions of what the "best" one is. It's better to focus on making a good product because your users don't give a shit if you used Redux or Mobx.


Clojurescript does include a bunch of things you have to use libraries for in JS. Such as immutable data-structures.


Yes, I think the language lends itself really well to working with React and writing UI code in general. But I understand that it's hard for a team to migrate to an entirely different language so I get why people use React or Redux or any of those.


Absolutely, and Elm bakes the React+Redux model into the language itself and makes it all a lot smoother and cleaner to do - but it doesn't play nice with a lot of JS libraries which you could use fairly easily with React/Redux.

Always tradeoffs, sadly.


This puts a lot of logic in your components. This isn't necessarily bad for small apps, but it's hard to test and it's really bad if you have a react-web + react-native app where you'll be writing platform specific components


I agree, MobX felt much more natural to me when dealing with CRUD-style apps, there was very little boilerplate. Redux is great for apps with extremely complex workflows, but that's fairly rare in my experience.


Redux is for people who appreciates immutability. A lot of newbies don't appreciate immutability.


A lot of seasoned developers don't either.

Because they've read "No Silver Bullet" and know a specific solution sold as a panacea when they see one.


Agreed. We're moving things from Redux to Mobx, and I would definitely use it for any new React thing I felt the need to build tomorrow.


As someone that has recently started using Redux over Flux, how does Mobx handle nested dependencies? e.g. when you change selected item in store 1, it will impact items in store 2. (Redux doesn't have a great solution to this - it puts it all in the action handler - but it is consistent and means you components don't need to understand any of the store logic.)


You can have a computed field in store 2 that computes the items based on the observable item in store 1, Whenever item 1 changes, the computed observable is updated automatically


It's one of the simplest things ever. Problem is the docs. Could be reduced to a readme. Too much ado about a tiny simple module. Just look at the code. It's nothing.

But it also does nothing much.

Now Relay...


I'm glad that the author mentioned sagas - this is one of the most underrated parts of using Redux and it makes a huge difference in async code. To be able to define complex asynchronous tasks as a series of "take", "call", and "put" has significantly reduced the number of bugs in our async code.

Another point for Redux: it makes it much easier to understand bugs, both locally and remotely with a tool like our LogRocket (https://logrocket.com)


LogRocket is truly fantastic.


Some of these points are basically principles of (object-oriented) software composition, just applied to react. Some examples:

- "Multiple simple components are better than one highly customisable one" -> Single responsibility principle [1]

- "When all you have is two weeks, keep it lean" -> "Make It Work, Make It Right, Make It Fast." [2]

- "embrace the toughest linting rules your team can stand." -> Not really a principle, but that's almost like simulating statically typed language with compile-time errors and warnings.

[1]: https://en.wikipedia.org/wiki/Single_responsibility_principl...

[2]: http://wiki.c2.com/?MakeItWorkMakeItRightMakeItFast


sagas are a steep learning curve and absolutely knowing what a generator function is essential before opening the docs. They are a very productive tool and worth the time imho.

They allow your redux containers to concentrate on selecting state and triggering actions and the async stuff stays out of the way in 'workers'.

Defo worth a look if your redux project has more than a few pages.


Redux saga is so elegant it makes me want to cry - but you have to understand generators first, as the author states. Once you get that part, then there's really no going back. Much simpler (and far lighter) than redux-observable.


I'm using redux-observables (very similar conceptually to sagas but uses rxjs) and allowing redux actions to remain pure and synchronous has made testing a breeze.

Middleware has quickly become the most important redux feature for me.


> 4: Raw SVG >= D3 for simple data visualisations

You can have a bit of both. D3 has a dependency "d3-scale" [0], which is a perfect choice if you'd like D3 to do the math and React to take care of the DOM.

0: https://medium.com/@mbostock/introducing-d3-scale-61980c5154...


Yesterday I wanted to find horizontally scrollable JS charts and had a hard time.. any tips?


> My tip: test on lower spec machines

I wished ever developer would do that. Too many mobile apps or websites that do very simple stuff (displaying content, simple forms) don't work properly on older phones because of some sophisticated features that no one needs. Many developers seem to think that everyone uses the newest machines and flagship phones with high bandwidth, and forget about everyone else.

Unfortunately the fear of premature optimization is so big for some people that their users have to suffer just because the programmer wanted to have a nicer developer experience..


The real reason people don't do it is because it's really hard to make a part of your CI workflow. If the organization wants to dedicate resources to this, great, but this isn't something the dev team is really equipped to do all by themselves.


It's definitely hard to do but tools like Selenium and Selendroid can make it easier (assuming you have someone who has the time and energy to set it up).

Once you have system level tests running, then adding some phones or low-end machines is relatively straightforward.


Are there any CI SaaS tools for this?


Tangential question: does anyone have experience moving from full time (.NET) development to freelance React / JavaScript development and is willing to offer advice?

I'm currently employed as a senior .NET consultant and I am seriously considering changing stacks and trying contracting / remote work in order to have more freedom to travel and work from different geolocations amongst other things.

Should I take some time off to learn React? Do I have to position myself as a junior React developer?


I think it is worth it. Once you get a grasp of React (and get a working webpack setup, which was difficult in the past) allows you to build apps for mobile (React native), desktop and web.

We're hiring react developers in Hamburg, Germany :)


Great, thanks for the heads up! :)

Do you have any more information about your company, vacancies and hiring process?

EDIT: a quick search has answered my question- no REMOTE positions I see :). Hamburg is a nice city though!


Oh we're just a small startup with a node.js / react platform hosted on AWS. Due to our small size we have a simple and short hiring process, in which we try to hire smart, experienced people.

As the sibling comment said we're also very open to remote working after a certain period of getting to know each other.

I've refrained from adding the "REMOTE" keyword to our hiring posts because it attracts a lot of remote (non-)"talent", and we're being swamped in mails from people who don't fit the stated profile.

We've been burned hard by remote-only employees in the past because it is very hard to keep the whole team on the same page, even more so with programmers inbetween junior and senior who want a lot of autonomy but end up delivering subpar results.


Generally you'll find that a company is way more amenable to going full-remote after a few months of having you in the office at least three times a week. Just bring it up during phone screens whenever they ask "do you have any questions for us," after the obligatory company-focused question.


One thing I don't like about React Native is that you need a Mac... :(


Why do you need a Mac...?


Deliver anything to iPhones..


Why is that React Native's fault?


Its not, its just that people compare it to Phonegap, Ionic, etc...


> does anyone have experience moving from full time (.NET) development to freelance React / JavaScript development and is willing to offer advice?

To me that looks like 3 different things - going from .NET to web dev, going from full time to contracting, and learning React. I wasn't .NET exactly, but went from Windows C++ game console dev to web dev, and I'm currently doing React contracting.

I love web dev, and I don't want to go back to C++. That said, contracting takes a lot of learning and is hard to get used to. Many consider not switching everything at once, but focusing on learning on big thing at a time. React is great to learn, but it's early and time will tell if it sticks. There's a ton to learn about web development that is independent of React.


.NET probably means web developer. There's game dev with Unity, granted, and a few jobs out there doing mobile work with Xamarin, and I imagine some windows only app or tools development, but the majority of .NET work seems to be web dev nowadays.

You do make a good point, though.


Those are good points, thank you. .NET for me is mainly web dev, and I know some JavaScript (and JQuery), but it will be a bit of a shock to the system nonetheless.


We're hiring .net developers, we cross-train on react. So, if you want a lower risk way of getting into react, drop me an email.


I find mockable end-to-end testing for React-based SPAs to be quite a mess. On the one hand, "React is a just a view library" so e2e testing is orthogonal. On the other hand, Redux/Flux + React pretty much get treated as the counterpart to traditional MVC and the infrastructure upon which you build your whole app on. But unlike Ember with it's QUnit e2e helpers or Protractor for Angular, there is nothing like that for e2e testing a "React [+ Redux/Flux]" app. Unit testing with TestItils/Enzyme/Jest definitely doesn't cut it. You can unit test all day but the isn't the same as integration and acceptance-type testing. We had to basically roll our own using WebDriver.IO and injecting a fetch-mock helper into our app to mock out the external API calls. That last part is key when you need to test your complex SPA without having to rely on backend API servers. Anbody else feel this pain?


You're completely right! It's unfortunate but the tooling for e2e tests isn't "there" yet. For now the best alternative is Selenium (which I've had a lot of trouble with getting stable) or https://github.com/DevExpress/testcafe


what i've found over the course of my career is that the most invaluable feature of boilerplate and scaffolding apps is to get a known-good build pipeline up and running. a trick i've often found useful when migrating to a new framework is to autogen a starter project and then start copying bits of my existing project into it and getting them working. when i'm done, i usually understand the new system well enough to go backport my changes to the existing project (if i want to preseve git history) or simply start afresh once all my tests are passing.

it is a sad commentary on the state of software development that the build process is the most complicated and headache-inducing part of exploring a new language or framework, but i've found that to be a constant across many languages and many years.


Try create-react-app


> My tip: embrace the toughest linting rules your team can stand.

How good is the Flow type checker, vs ESLint or the Google closure compiler?

While I don't disagree with anything the author said, most of the time I feel like ESLint is just a huge nag about white space. It's defaults have a bunch of rules that in my opinion enforce style without improving code safety at all, despite what the intro docs say. Someone I work with read some opinions like this one and got the idea that ESLint represents correct JS standards, and won't allow the white space rules to be relaxed. I'm stuck being forced to put a space after my comment characters, and not being able to line up blocks of repetitive code. It is admittedly nice to not have any white space style arguments. OTOH, I never really had white space arguments before, and the difference in both friendliness and code safety between using ESLint and the Google closure compiler is huge.


For all the people who use redux - a question - how is redux better (for your use case) than just a global variable?


Lots of reasons:

- Isolation of "write logic" means you know where to look to see what code is updating a given chunk of state

- Consistent state handling means it's a lot easier to think about what's going on in the application

- The DevTools show you a log of dispatched actions, and enable you to step back and forth between states to see what the UI looked like at each point

- Middleware lets you centralize app-wide logic, such as consistent transformations for AJAX responses

- Redux's constraints (such as wanting state to be serializable) enable a number of other use cases, such as persisting state across page reloads and synchronizing multiple stores remotely.

- There's a rapidly growing ecosystem of addons and utilities for specific use cases (see https://github.com/markerikson/redux-ecosystem-links )


I've built a pretty large react app and never needed these things.

Things like stepping back through state seem honestly to me to be a gimmick not worth the required investment of time and pain.


I've seen a number of people make comments to that effect, and I genuinely don't understand that point of view. I use time-travel debugging on a daily basis, and it's a _huge_ time-saver for me.

I also don't understand the "required investment of time and pain" comment. I've got a couple lines in my store configuration that sets up the Redux DevTools extension, and after that, It Just Works (TM). In fact, one of the posts in my "Practical Redux" tutorial series shows how to configure it: http://blog.isquaredsoftware.com/2016/11/practical-redux-par... .


It is conceptually like a global variable except changes to it are strictly controlled.

So in that sense it is a very close representation of reality.

The reality is that the state of your application can be (and I'd say should be) perfectly presentable in a giant object.

Redux is not shy about that and doesn't try to hide or escape from it. The importance is in how you manage reads and writes.


Returning a new object whenever data changes (poor man's immutability) gives you time travel / replay / undo, and makes debugging straight forward. All data changes happening in the reducers decouples the UI actions from business logic.

Redux only looks complicated because it tries to gracefully catch every possible user error, and has a bit too many layers of functional abstractions. You can implement the whole thing in a few dozen lines of code.


Reducers are pure functions so they can be tested very easily. Also the whole middleware thing and redux logger are awesome.


Redux has several components - actions, reducer(s) and the store.

Why actions? Actions give you an explicit API between the global variable manager(the store) and your components. For one-off components that are cognizant of the fact they're part of an "App", this isn't very useful - e.g. if you want the component to insert "foo" instead of "bar" into your global state, you just go and modify it. For reusable components, however, their interface may be locked(used by other parts of your app or even different apps!). Then you need some kind of adapter to turn the "foo" they give you into a "bar" - actions are one such adapter.

Besides that, actions are one part of the "state machine" design that redux implements. Actions enumerate the possible ways your state can change. Is your state meaningful if you change global.foo = "bar"? It might be, or it might not. Actions are a contract between those modifying the state and those consuming the state, that all changes to the state will leave it in a coherent...state! Even MobX, which essentially takes your "global variable" idea and runs with it, advocates for actions.

Having this guarantee is great for debugging. Is the global state mangled? The global state manager code must be broken, since everyone sends actions, and the only one consuming the actions is the manager. You don't have to hunt for a rogue component that's setting global.foo = "bar" instead of global.foo = "baz". Once your global state manager is ironed out, your problems are less "why is my state mangled" and more "why isn't the component sending the expected action".

In theory, this should simplify your debugging a lot - you are not trying to disentangle a complex set of interactions that led to your state being mangled and a component failing from that, but rather you're just looking for the one component that isn't sending its actions properly. Redux's debugging tools try to highlight this, with the action logger and so on.

In practice, how useful this is depends on how you've designed your actions and global state manager. It is entirely possible to write a trivial global state manager and essentially place all your logic in the actions(for an extreme example, imagine a state manager that accepts an action "set" with a "key" and a "value" - you haven't actually gained anything then!).

Why reducers? If you're convinced that a global state manager and actions are a good idea, you are now stuck deciding how exactly to implement this manager. Let's say you have a yet-unwritten global state manager. You know the current global state, and you've just received an action. A reducer is function with the signature (state, action) => newState, essentially implementing a global state manager! Redux goes a step further and asks that reducers are "pure functions" and that the state is immutable and replaced instead of modified. The reasoning here isn't specific to Redux and it's once again related to consistency and debugging.

Do you really need all of this? That's a good question, and I think it really depends on the project. You may have heard people advocating that you don't use any local state and put everything into Redux. This attempts to solve the "reusable component communicating with others" issue, which by the way I don't think Redux solves well(there's tons of 3rd party libraries trying to deal with that). For this specific case, I think "global variable + event emitter" is a decent solution.

What about more complex state interactions? Well, for them I think the concepts Redux introduces are incredibly useful - not having to worry about your state's consistency is a huge help in debugging. Does Redux itself really deliver them 100%? Well, quite often a lot of your state changes will be coupled with side effects, ranging from animations to API calls. Without carefully designing your reducers, the side effects will quickly eat up any benefit - you may be stuck debugging "why doesn't my action creator pass the appropriate action to my trivial reducers". This is a point that Redux doesn't really handle - there's lots of middleware, addons and full-blown libraries trying to deal with the issue(e.g. redux-thunk, redux-saga, and so on).

My personal opinion is that the concepts that Redux tries to introduce are very useful to know and keep in mind when designing your system. Whether you should commit to Redux the library(and its accompanying middlewares and so on) is a different decision. I think I've learned a lot from studying Redux and thinking about the concepts it tries to introduce. However, all the benefits Redux provides depend heavily on the design of your actions and reducers. With a poor design, you are stuck adding more boilerplate for no gains. This is why I wouldn't use it in many of my projects - I don't think I have the experience to design my state management in such a way as to extract significant value from Redux, without being bogged down by the extra boilerplate.


I love this comment.

After a lot of evaluation of different js frameworks over the last year I reached the same place with Redux. The principal is sound; it's clean, simple, and incredibly easy to understand. Ultimately though, your logic can end up scattered about the codebase and I worry about what these codebases are going to look like in a year's time.

With MobX you can take a cue from Redux and enumerate all your actions. You're then free to apply the same strictness as you have with Redux in terms of the actions and dataflow.

When people compare Redux to MobX, the thing that is always missed is that MobX provides patterns for efficient calculated / aggregated state. There's no logic in there - it's just a way of transforming your raw state into a read-only structure more suitable for your views.

I guess the situation we've got now is that there are a lot of people who have gone deep on the Redux approach. And really - the code looks like Redux, which is one of my major concerns. When everyone decides that it's hard to manage the sprawling logic of a big Redux app it's going to be very hard to transition to any other pattern.


It helps you sieve the global variable so components get just the data you say they should get.


Anyone working on Windows? Is web pack still the way to go? How does it interact with something like phonegap? I have 3 similar projects and I'm super confused which stack should I pick...


webpack is still the way to go. Windows or not.


Given the amount of React knowledge in the thread and the fact that I just finally groked Redux... what would you recommend to emulate something like ionic? MaterialUI + some sort of flexboxing?


For a material design look, I've used material-ui, mdl, and react-md. react-md is the best in my opinion. Incredibly complete and polished for being done by essentially one person. https://github.com/mlaursen/react-md


This is great advice, particularly the part about small, similar components instead of large, customizable ones. This is something I feel like I struggle with in views much more than I ever did working backend, and it's healthy to be reminded regularly.

On the subject of sagas, does anyone have a good solution for dealing with `call` in TypeScript without losing type safety?


Other things I'd add after building a React project:

1. "Configuration over Convention" seems to be the mantra with build settings and organization of the entire application. This can make adding features slower if you're used to frameworks like Rails.

2. SEO will require additional effort via server side rendering


"Linting also helps catch errors like reassigning consts and speeling errors"

Hehe.


Now I don't know what to believe: https://imgur.com/gallery/jL62c


I don't know if this sort of thing has me concerned or optimistic. On one hand, most ecosystems have a set of standard practices ("best practices"). This can take a lot of ambiguity out of learning and using a new ecosystem. On the other hand, some communities have chosen best practices that seem a little odd (I'm looking at you, PHP. If I wanted to write code in Java, I'd use Java).

If nothing else, this makes asking React based interview questions complicated.


Don't use it. I used something called JS stack from scratch (it's a github repo). You set it all up but along the way it teaches you everything. It worked perfectly. The only JS I'd done before that was Backbone stuff and requireJS.


I'm more of a fan of Vue and it's CLI launcher, I was just pointing out the two high-visibility opposing views which I'm sure add to the frustration.js that devs old and new experience.


I about to convert backbone views in a standing app to React components. Then eventually convert the backbone app to React much later. Do you have any advice, tutorials, and code repositories that would help me?


The "Thinking in React" doc on the main React page, and their tutorial, were greatly helpful, and it was about 80% of my reference docs. I didn't bother with trying to interface with existing Backbone models, but your app may be too huge to rewrite (it still took me several months to rewrite from scratch, but it's a side project so it probably would have been a few weeks if full time).

That "js stack from scratch" repo is also very helpful in setting up the whole build.


Definitely agree with #1. If there's one way I've changed as a programmer as I've gotten more experienced, it's that I DGAF about repeating myself.


Don't rely on lint to catch speeling errors. It doesn't work on imports. Flowtype or TSC (even without using any TypeScript syntax) are your friends.


Excellent article! Lots of tips that are applicable to non-React projects as well (simple over customisable components for example).


Anyone working on Windows? Is web pack still the way to go? How does it interact with something like phonegap?


And it's only been a year! <3. Wild ride.


> Happy 2016?


> January 2016, I changed my job title on LinkedIn to React developer

So whenever I start working on a new area, I should add that to my job title?

React Carpenter?

http://www.jasonbock.net/jb/News/Item/7c334037d1a9437d9fa650...

Also:

> 1: Multiple simple components are better than one highly customisable one

No shit. Ever heard of UNIX?


I would recommend Cx to all React contractors. Cx runs on top of React and solves many React/Redux pain points. It also offers comprehensive widget library and charts.

http://cx.codaxy.com/

Disclaimer: I'm the author.


This is a library that seems to do something a lot like what lots of other libraries do, except this one costs hundreds of dollars per developer, comes with only a year of support, and has many obvious problems with its licence such as being revocable, being ambiguous about jurisdiction, and literally having the word "DRAFT" stuck at the top of the first page.


The licensing stuff is hard. I believe that our license is fair, even if it's complicated.

You're right, many free projects offer the same or even greater functionality, however, you're not taking into consideration time you spend to put everything together. If your client is paying you hourly, Cx is an investment which pays off quickly. We're contractors too and this was one of the reasons behind Cx.

I understand that commercial licenses are not very popular these days, but for a small company like ours, I don't see any other model allowing us to concentrate on support and the product in the long term.


I do understand that it's a tricky market to work in commercially. I have nothing against charging for your work if it provides the value to justify it, and similarly I have nothing against developers paying for tools that will help them do a better job and/or save time. Your site didn't sell me on why your particular product is better than what I could do with other tools, but obviously that's a personal judgement and others might take a different view.

I also appreciate that writing a good licence is hard, but yours does seem to be particularly awkward. For example, if we're developing a project for a client, our terms typically state that they will have a certain minimum standard of licence for any third party code we use, so they know they're in the clear deploying or distributing whatever we build for them. Your terms giving only a revocable licence would immediately disqualify your library, as would any other hedging about being able to use it indefinitely once it was paid for.


The license is perpetual and can be terminated only if Licensee breaks the agreement. I don't see how that can be an issue. Can you please explain the problem?


The stated jurisdiction is unclear and the main licence term includes the word "revocable". Unfortunately, that combination alone means the licence would contradict our usual guarantees to clients. These typically say we will only incorporate third party elements when the client has a perpetual and irrevocable legal right to use and redistribute those elements as part of whatever we're delivering. The furthest we've ever stretched this is including FOSS with widely recognised licences where there may be a well understood obligation on the client to provide the source code on demand, and some clients won't be happy going that far.

The bottom line is that our clients don't want to get bogged down with the terms of third party contracts or licence agreements and whether they could undermine the whole project, so anything with the slightest hint of risk is immediately more trouble than it's worth in this sort of area.


> I would recommend Cx to all React contractors.

But your licence scheme seems to favour devs who only work for one company a contractor would get a new one for every project.


That's true. It's your client who should provide the license. I guess if you're switching projects very often this is a problem, so feel free to contact us and we'll come up with a model that works for you.


It took me a while to find the license. To save others time: http://cx.codaxy.com/CxLicenseAgreement.pdf

I don't understand whether this license is reasonable or not (setting aside price) - which is a problem. Most developers will not hire a lawyer to parse the 7 pages of legalese.


This is a valuable input. Thanks. We'll extract an abstract and put it on the license page.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: