Hacker News new | past | comments | ask | show | jobs | submit login
React: Mixins Considered Harmful (facebook.github.io)
287 points by tilt on July 13, 2016 | hide | past | favorite | 199 comments



I like how core features of React are being considered harmful. First it was component internal state, now it's mixins and next thing will be the lifecycle methods.

React components will then boil down to pure render functions. React will then be replaced by simpler VirtualDOM implementation. JS function declaration boilerplate will be removed from render functions, so they will be more HTML with some JS as the other way around. Also they will be called templates.

We are getting back to good-old-days PHP-style webcoding, but with few HUGE improvements.

1. no globals, mostly pure functions

2. no business logic in templates, but in easy-to-reason-about redux-style state reducers

3. client-side rendering / isomorphic apps possible


>First it was component internal state

You won’t find any place in React docs that claims internal state is harmful. There are some guides claiming that but this is not the official position (and I say this as author of Redux and a member of React team). We use state a lot at Facebook, and it’s a large part of what makes React useful.

>next thing will be the lifecycle methods.

Lifecycle methods are also fine. Sure, it’s best when there aren’t too many and they don’t do too much, but it’s a supported feature for a reason. It is occasionally super useful. They aren’t going away.

>React components will then boil down to pure render functions. React will then be replaced by simpler VirtualDOM implementation.

This is an explicit non-goal of React. We think stateful components with lifecycle methods are very useful. If you don’t agree, however, React is indeed not the best choice for you, as it does too much.

I’ve read a lot of misconceptions around React so I plan to put up “Design Goals” document in the repo so people can get a better idea of the direction that we’re moving into, and why.


>You won’t find any place in React docs that claims internal state is harmful.

But it is the first principle of Redux

The state of your whole application is stored in an object tree within a single store.[1]

Am I getting it wrong?

>I plan to put up “Design Goals” document in the repo

That would be great. The "why" is sometimes hard to understand.

[1]http://redux.js.org/docs/introduction/ThreePrinciples.html


I think you are confusing React with Redux. They are two very different things. You can use them together but Redux is not the “default” way of using React.

>But it is the first principle of Redux

Redux is a very opinionated library and it is not related to React in any way. React does not officially endorse Redux. If (and that’s a big if!) React patterns don’t scale for you or if you personally prefer Redux to them, you can use it, but a Redux app !== a React app.

Which doesn’t mean either of them is the “right” or “wrong” way. Learn React first and try to use it. If you have issues related to state or if you’re just curious, you can also learn Redux to compare their approaches. If you like, you can combine them, or use them separately.


I had an impression, that React community (not the authors) considers Redux as an best-practice. My first post was a little bit exaggerated view on where is this whole React-based website developement (including Redux and other libraries and tools) going, not only the React itself.


>I had an impression, that React community (not the authors) considers Redux as an best-practice.

A part of React community, yes. Another part, no. Guess which part is vocal because they can write tutorials, examples, articles that generate clicks? ;-) I am as guilty of this as anyone of course, if not the most.

Obviously React has some deficiencies addressed by Redux. So does Redux have deficiencies addressed by React. Eventually some of the ideas from Redux might make it back into React.

However I suggest learning to build apps with React itself first before using more radical approaches like Redux. You’ll benefit immensely from knowing both ways. I would not necessarily put trust into articles saying “X is the best practice” or “Y is an inferior paradigm”. I would, however, listen to somebody who says “we tried X and Y, and here’s what worked best for us and why”.

>My first post was a little bit exaggerated view on where is this whole React-based website developement (including Redux and other libraries and tools) going, not only the React itself.

Ah okay, sorry then! These are both interesting, albeit different directions. I think it’s easy to misunderstand them as an “evolution” whereas it’s really a “fork” (in the traditional, non-technical sense). These are two separate ways, and both lead to interesting but different things.


I did. I started with React itself. Then I added Redux (first time, it was beacause of the project manager decision).

I really like the state reducers.

I find internal state clumsy, beacause you have three kinds of functions around the very same state object - get initial state, get state after some props changed and get state after some user action. For simple cases they are very similar to repeatedly write, but still different to abstract out.

I hate putting everything in One-Rules-Them-All Redux Store (specially form input on each key press), beacause it creates too much little components to glue it all together - Action declaration, action generator, reducer implementation, projection from Store to component's props

I did not see any good solutions that take best of both approaches and I was tired searching. But I plan to wrap my brain around this and think about what exactly is bothering me and how to solve that. In first sight it is what I outlined in my first post. The next thing comes to my mind are Redux-style reducers for component's internal state.


I hope this helps:

    dispatch(action) {
      this.setState(prevState => reducer(prevState, action))
    }


Hmmm, that'd be sweet in a mixin...

ducks


I never put everything in the one-big-store that rules them all either, but you don't really need to do that.

Alternatives:

- internal state (sometimes useful, especially for small things that doesn't matter for your underlying data - eg, "is this part of the tree unfolded"). Preferably, with very little logic linked to that state. Note that it can bite you if you use something like redux-undo on your store and your internal state refers to the data controlled by the store.

- temporary stores (create a store with a callback function in an event handler, and feed it a callback that invokes an action on your main store)

- smaller, specialized stores that get a projection of the data of you main store (this gets a bit awkward with async actions)

I'm also trying to avoid fully-controlled text inputs with textareas, I use wrappers with local state which send their content via onBlur().


The majority of developers don't have the time or interest to dig deep into nitty gritties of the React community & ecosystem. They read articles including yours and quickly become indoctrinated into thinking how (for example) putting ALL state into a redux store is a proper way to work with React.

This leads to hilarious codebases where people dispatch actions in order to update input values or navigation dropdown open/closed states etc. Trivial apps that could be built over a weekend end up taking weeks to finish.

It's a sad reality but most people (including developers) take everything they read at face value and don't devote enough time to critical thinking. We should try to combat this.

I'm not saying it's your fault (it's not, you're great), but perhaps you should put a bit more effort into stating how what you're propagating is just one way of writing code and shouldn't be used in all situations (especially simple apps). I've actually seen you do that in a couple of places in the past few months and that's great.

I do feel a bit bad about sitting in my chair criticising while you're contributing with all this awesome stuff but you know... with great power comes great responsibility :-)


I can't speak for the community as I've been using React/Flux for under a year, but I think that Redux and other Fluxes serve a very different role from component state, and using Redux/Flux to store all your state will cause problems with both performance and code complexity.

Redux manages the state of your application as a whole. But individual pieces within the page have no reason to know about the page state. Likewise, there's no reason for your Redux stores to concern themselves with the detailed workings of every component. Why should your app care what's going on inside a button or a menu? That leads to gigantic, overcomplicated states. Let the components manage things for themselves.

A good rule of thumb might be that if three layers of components need to know about a piece of data, it might be good to consider moving it into a store. But if it's only a component and its child components that need to know about it, you're not gaining much by moving it into stores--the stores and actions you'll have to implement are just added complexity. It's incredibly frustrating when I come across code where I have to push data through an action and a store and dispatch when a simple call to setState would have done all the same things faster and with less code.


My observation is that going with local state is going to bite you sooner than later and in most cases having it in Redux Store from beginning is a good idea.


This has not been my experience. I wrote a good amount of React before introducing any Flux at all, and I've been bitten far more by my mistakes where I added things to stores unnecessarily than I have been by cases where I kept things in component state. Your experience might be different from mine.

It's my impression that a lot of people are coming from a Angular or Ember-ish background where they're building what amounts to single-page web applications. I'm building multi-page apps that have heavier-lifting back-ends, and React fills the space of building components that can be composed and embedded in the page.

When you're building a single-page app, stores make a great deal of sense. But when you're embadding components in a page, it doesn't make sense to use stores. Not only do I not want to have my components interact, I want to actively avoid having them interact, because that coupling would make the components non-reusable. So tying them to a global state presents serious issues for that model.

It occurs to me that this might account for our difference in perception of the importance of stores.

P.S. It's also worth noting that moving state out of a component and into a store is fairly painless. The reverse is not true; moving state out of a store and into component state is an extremely painful and error-prone process. So it makes sense to start with component state and move things into stores only as needed.


I recently made a slider in React/Redux. Imagine a slider that has a width of 200px but needs to report values from 0 to 100. (The width is governed by external factors, e.g. other sliders nearby that need to report a widger range, but must visually be of the same width.) This means that sometimes you may move the slider just by a pixel and need to register the movement, but the underlying value won't change. I.e. you have the slider offset and the actual value.

The slider offset is a very transient variable that is not really important. Next time you load an object from the database you'll just convert the value to a slightly different offset and nobody will notice. Are you going to store the offset in the big store?


Dan,

First, thank you for all you do. Huge fan, and you're an asset to the community.

One question I have is around this quote:

> Learn React first and try to use it. If you have issues related to state or if you’re just curious, you can also learn Redux to compare their approaches.

I tried to go down this route with a new employee who I've positioned on a React project (mostly as means of exploration + learning in between other projects)

But as soon as I had to deal with fetching data from the server and pushing it back, I felt the need to jump into Redux. Yes, I could manage this in React, but as soon as I had two "pages" in my app, I feel it would become unwieldily note to use the Redux + Redux-Think (or Sagas) combo.

Am I wrong here, or am I just "comfortable" with Redux, and thus, not persuing the idea of trying to build a more featured app in pure React?


I don’t know, whatever works for you :-) I’m just saying that both ways can work fine.


What are your thoughts on just simple es6 classes and mvc? View=React, c=es6 class, m=immutable js. I use page.js for my router and call it a day.


> easy-to-reason-about redux-style state reducers

This buzz phrase "easy to reason about" is so popular in the React world. I feel like I'm the only one who finds it oxymoronic. Especially with regard to Redux, which I think is anything but.

Angular 1/2, Ember, Backbone are all pretty "easy to reason about", so much so that it is rarely pointed out.


What do you find hard to reason about when it comes to Redux? There is some terminology, but the heart of Redux is a pure function that takes a state, new information, and returns a new state. That's hardly rocket science.


You are definitely not the only one who has not found Redux "easy to reason about". I think the concepts are somewhat straightforward, but in practice are a little harder to grasp, especially in real world applications.


> the concepts are somewhat straightforward, but in practice are a little harder to grasp, especially in real world applications.

Well said.


Component state is hardly considered harmful. What has given you that impression?


not exactly harmful, but in the docs they promote stateless functions by saying:

"In an ideal world, most of your components would be stateless functions because in the future we’ll also be able to make performance optimizations specific to these components by avoiding unnecessary checks and memory allocations. This is the recommended pattern, when possible."

See https://facebook.github.io/react/docs/reusable-components.ht...


That's more because most components are render-focused, which means they're more concerned with props than with state. Of course, a particular render component might also have its own state (imagine a list with pagination for example), which isn't required by any of its parents or siblings.

However, state is something on the whole that's required more often higher than lower in your architecture.

I'm pretty sure that's what they're talking about here. Hope that helps.


Not sure what you mean on component state, as I've never heard anyone say that is explicitly harmful, but I think what you might be getting at is the principal in react of creating MINIMAL state such that any logic - for example something that renders an item - can compute off that MINIMAL state, rather than creating a new state that's the result of processing that basic state. The example given in Thinking in React[1] is having an array in state, but computing it's length somewhere (say in render), rather than making the length of the array also part of the state.

On this note, I find that I rarely use state in child components, because as much as possible I have functions that compute values off props and simply return that where I need them, rather than storing them as state variables.

[1] https://facebook.github.io/react/docs/thinking-in-react.html


I'm not familiar with React's mixins, but I get the impression from the suggestion to use higher order functions that it doesn't allow overriding methods from other mixins. E.g. Scala's concept of stacking.

For those interested in the concept in JS, I implemented a full trait system in GNU ease.js designed around Scala's approach, with support for stackable traits. The system also supports protected/private properties and methods, which can also be taken advantage of in traits to provide public and protected APIs, and keep state encapsulated in traits. I don't have documentation available yet (soon), but I do have a great many test cases that demonstrate various aspects:

https://www.gnu.org/software/easejs/#traits https://www.gnu.org/software/easejs/news.html#d9b86c1

Hopefully others find this to be interesting even if they don't agree with ease.js itself.


The decorator-based approach sounds interesting, but (in my understanding) it will require moving the data fetching logic away from the main component into the decorator, which also creates a level of indirection that is intransparent to the component user, and I imagine stacking several of these decorators on top of each other should provide plenty of room for unforeseen side effects as well.

Personally, I think almost all components should be "dumb": They should just receive the stuff that they display as properties from their parent components and report changes back through callbacks. They should not perform any "controller logic" beyond form validation and input serialization. Only a few components at the top should be responsible for fetching and distributing resources from the backend. Typically, it should suffice to have an "Application" component that takes care of fetching stuff that every other component should see (e.g. data about the user), while components one level below the application should fetch stuff that is specific to the given page/view that is being displayed.

Unfortunately, compared to the humble beginnings a few years ago I feel that the whole React.js stack gets more and more bloated these days. As an example, managing state through Redux requires writing actions, reducers and implementing a subscriber pattern in my components, just to fetch some data from the server. I mean, if we're writing a version of "Photoshop" for the browser this level of complexity might be warranted, but in most cases we just want to fetch some JSON, display it nicely formatted to the user, let him/her click on it and possibly send some data back. If we need 500 kB of Javascript libraries to do that while having to patch/reinvent many other things that we took for granted before -like simple hyperlinks (I'm looking at you, react-router)-, chances are we're doing it wrong.


>it will require moving the data fetching logic away from the main component into the decorator

We are not suggesting you to do anything like this.

The article was about migrating from mixins to patterns like higher order components. If you do your data fetching right in the component, we are not suggesting you to change anything. It’s only mixins that we found problematic, and we are just sharing our experience migrating away from them.

>the whole React.js stack gets more and more bloated these days. As an example, managing state through Redux requires writing actions, reducers and implementing a subscriber pattern in my components, just to fetch some data from the server

Redux has nothing to do with the “React stack”. React is just React; if fetching data in components works great for you, why are you migrating to Redux?

>I mean, if we're writing a version of "Photoshop" for the browser this level of complexity might be warranted, but in most cases we just want to fetch some JSON

Redux is overused. Nowhere in the article do we recommend to use Redux. The article is about mixins.


Thanks for clarifying this! Maybe I misunderstood the example in the article that migrates the subscription logic from the component/mixin into the decorator. This was what made me question whether this will be more efficient/scalable than using the Mixin approach, as there is also some indirection here.

Concerning the whole Redux issue: Yes, of course I can -and do- use React without it, but the problem is that everyone else seems to rely on these tools and see them as an integral part of the "React experience". I find this problematic as it makes many components less portable, as they are bound to a given router / state loading paradigm.

I think it would be great if there could be a bit more emphasis on "keeping it simple" in the React tutorials, as I see a lot of (often unneeded) complexity popping up in the frontend world, and I think this will cause a lot of issues in the future.


>migrates the subscription logic from the component/mixin into the decorator.

It was not migrating the logic from the component. The example was about getting rid of a mixin. I think the article even mentions the opposite:

“If there is just one component subscribed to this data source, it is fine to embed the subscription logic right into the component. Avoid premature abstractions.

>the problem is that everyone else seems to rely on these tools and see them as an integral part of the "React experience"

Who is “everyone else”? I think you might be listening to a vocal bubble. As Redux author, I can tell you that it is not in any way essential to React. Some people use it, many people don’t. Solve your problems, don’t just follow what you see in flashy magazines.

>I think it would be great if there could be a bit more emphasis on "keeping it simple" in the React tutorials

I think this is exactly what React tutorials do:

* https://facebook.github.io/react/docs/tutorial.html

* https://facebook.github.io/react/docs/thinking-in-react.html

We can’t really control what third party tutorials write.


Thanks again for clarifying, I don't want to criticize the work of the React authors or the community (which is outstanding), I'm just voicing what I observe from my "vocal bubble". Maybe I really spend too much time on HN :D


Yea, no problem. HN can be super misleading. I suggest to build apps and learn from the experience instead. ;-)


> I find this problematic as it makes many components less portable, as they are bound to a given router / state loading paradigm.

Interesting, I find if you "reduxify" everything, even the top most component becomes somewhat dumb and agnostic. With react-redux, it won't even be aware of the dispatcher.


Only if you have just one point where you _connect_ your components. If there are some containers deep in the tree then suddenly all your application is somehow tied to Redux. I've seen such recommendations from Dan to use connect often, but I find this problem a bit disturbing and not sure how (and if) to mitigate that.


I agree with your second paragraph very much. However, your third paragraph points out the adage that continually needs to be reiterated, and you kind of hint at it. If you are writing a basic app that fetches some json and displays it to a small group of users, then no, a framework stack like react/redux is not needed and you can stick to the basics. But when you have a complex application that needs to scale, react is a handy tool to help accomplish this task.

Furthermore, I think it's normal for react to bloat a little bit while programmers suss out new features and usage. However, hopefully paradigms will solidify over time and that bloat will start to deflate.. hopefully.


Data declarations via decorators for use by some data fetching layer sounds like exactly what I want.

> creates a level of indirection that is intransparent to the component user, and I imagine stacking several of these decorators on top of each other should provide plenty of room for unforeseen side effects as well.

Unforseen side effects ... that sounds scary! Though vague. Imagine there is some controller component (a currency conversion widget) and we're adding a dependency on "/exchange_rates.json". If we could add a hypothetical @getJSON('/exchange_rates.json', 'rates') at the top of the component declaration to make sure the "rates" prop is always either missing (loading) or present (successfully returned data, or an error response), that sounds great. It only takes ownership of one prop. Stacking decorators would work nicely. Am I missing the glaring avenues for unforseen side effects?


Awesome post Dan, thanks for writing and sharing!

One thing caught my attention:

>At Facebook, we extensively use traits in Hack which are fairly similar to mixins. Nevertheless, we think that mixins are unnecessary and problematic in React codebases. Here’s why.

>Mixins introduce implicit dependencies

>Mixins cause name clashes

>Mixins cause snowballing complexity

When I read these three reasons, I actually felt identified with them even outside React, since these as pretty generic problems in "mixin-like" cases that I've seen, for example Ruby modules. So it got my attention the fact that you're (at Facebook) using Hack traits successfully. Why is that? Are any of those reasons you stated not true with Hack traits? (Maybe you don't have knowledge in Hack though, but any high level conceptual idea may help).

Again, awesome post!


Traits and mixins are different. A trait/interface/protocol doesn't generally contain implementation, and when it does, it is based only on other methods in the trait (for things like default implementations), whereas mixins are just fragments of a class implementation with potentially arbitrary dependencies on methods.

So traits document the dependencies that mixins make implicitly.

Traits in typed languages can only cause name clashes if two methods in different traits have the same name and the same type signature. This is immediately obvious, and the compiler will warn you so you can fix it there and then when you try and implement them both for one class. (It also brings into question whether there should be another trait to hold that shared method).

The snowballing complexity that is mentioned stems from all those implicit dependencies: There's no way of knowing what they all could be in a nest of related mixins, whereas the corresponding traits document it and provide a map, of sorts.


Thanks for your response.

I can see how type checking helps with that in Hack, that makes a lot of sense.

Guess that in the case of Ruby for example we'd still have the same disadvantages as in JS right? Since there's still the possibility of calling methods in other modules and even in the class where the module is included, since that is discovered at runtime and you don't have any hierarchy that restricts who can call what.


Implementing mixins correctly in JS (which React does not) is already a well explored problem space.

I like https://leanpub.com/javascript-spessore for great explorations and derivations of various mixin patterns.

It's not that mixins are bad in general, it's that React doesn't implement them well in particular.


Thank you!

The code in JavaScript Spessore is ES5-specific, but I stand by the ideas discussed, including the one central to TFA:

  Naïve mixins solve the many-to-many dependency problem,
  but not the open recursion problem.
You can read the book online for free, but if you prefer the ebook format, here is a coupon for a free copy, good for today only:

http://leanpub.com/javascript-spessore/c/hackernews


Wow! Very cool to have the infamous Reggie drop in. Perhaps this is a good chance to say thank you for JS Allonge, which was my introduction to writing proper JavaScript. Before it I wrote code to make a feature work; now, it is equal parts getting it to work and crafting something elegant. Thank you!


Sure, it may be React’s mixin implementation that is subpar. However we noticed we didn’t need mixins (of any kind) with the patterns described in the post. Just components and functions turned out to be enough for our needs, and this is why we wrote this post.

I think the post specifically addresses this point:

>This doesn’t mean that mixins themselves are bad. People successfully employ them in different languages and paradigms, including some functional languages. At Facebook, we extensively use traits in Hack which are fairly similar to mixins. Nevertheless, we think that mixins are unnecessary and problematic in React codebases.

Maybe I should have highlighted that they can work well in JavaScript too—we just didn’t find a good use case in React apps at Facebook.


The thing is, mixins are a pattern, and patterns are interchangeable. So you can use composition, single inheritance, multiple inheritance, and mixins interchangeably in most cases. It's not that you need a particular pattern, it just might be easier to express a certain idea with a given pattern.

I agree with you that composition is easier to understand, since component APIs are well defined. For large teams like those at FB, this simplicity can be a big win.


Can you outline the biggest problems with React's mixins? I haven't heard this complaint before.


I'm sure you and @danabromov have more thoughts on this, but I would generally constrain the mixin system more:

- Don't let mixins call setState() directly; otherwise, it can be hard to track down what mutated the state. Have a well defined, canonical way to update state (proxy methods on the main component? Flux-style actions?)

- Don't let mixins define a render() method; this is the component's responsibility

- Separate mixin state from component state; mixins should not be able to see each others' state, and the component should not be able to see its mixins' state. Have a special API for a mixin to get its component's state (eg. this.getComponentState())

- Use vanilla ES6 mixins (class C extends mixin(A, B)) for interoperability with other libraries

Again, Spessore is a great exploration of how to implement these sorts of constraints.


I believe as time passes, we are moving away from the simplicity that made React win. Flux, Redux, higher order components generate too much complexity most of the time. React used to be simple, it still is, but the ecosystem and the mentality has gotten needlessly complex.


You can use React without Flux/Redux if that works well for you. The “mentality” is just people solving their own problems in a way that makes sense to them, and sharing those solutions.

As noted in the blog post, higher order components are not a React feature. And it is not related to Flux or Redux. It is just a thing you can do with components, like you can do it with functions.

We think HOCs are a useful pattern so we explain it, but you don’t need to use it if you don’t get value from it. (We got a lot of value from using it.)

That said if you have different solutions to the same problems that don’t suffer from the drawbacks of mixins, we’d love to hear them. This post is not there to force you to use HOCs. It’s for the people who had the same problems we experienced, tried to use mixins to fix them, and couldn‘t scale those solutions.


What I think OP refers to, is how there are so many different choices to do anything in the React ecosystem. It's cool that people share their work. But so many choices just cause decision fatigue.

It's hard to have any kind of real-world usage from just React. You have to learn and use some kind of Flux, routing library, AJAX patterns for that Flux library, another library for <inputs> and <forms>, etc. If you want server-side rendering, server-side data persistence or user auth, which you will in real-world cases, you have even more things to connect.

Also there aren't any free resources on the internet (that I could find) that teaches me how to put together a basic Twitter or Instagram clone using React + React ecosystem libs. No full-stack tutorials. Compared to Rails, React{ecosystem} is pretty hard to learn.

Unless you're an experienced senior dev and understand all the different technologies deeply, you can't make any informed choice about what libraries to use. You just go and pick the most popular ones and later doubt your decision and think that you could be having an easier time if you had picked some other popular library more suited to your project.

I guess most beginners just give up on React after trying a bunch of tutorials. I'm no Rails developer, but I guess even if you are a Rails developer with years of experience, you will find it frustrating to get started on React + ecosystem.


You really don't need to learn some Flux to solve problems with React. React works fine without Flux, or really any formal data layer; you can comfortably use it simply as a really nice view library.

I agree that people give up on React after tutorials that make them think about routing and Flux. It's a shame, because the core concept of React is incredibly simple, and anyone can pick it up in a couple hours.

Flux is a useful, experience-based contribution and I'm happy to have it as an option. But it's heavily cargo-culted.


This, much more of this, please. I've been part of a small react project that was doing just fine without flux. Then the tech lead, a enterprise Java guy, decided we needed to use Flux because it was the "best practice". Problem was none of us understood Flux or how the project would benefit from it. It was pure cargo culting.

Needless to say the whole thing became a huge mess as we spent all our time moving data to the store and back into the components. What is sad is that if the project had been allowed to evolve naturally, we might have ended up with a poor man's version of a Flux architecture, possibly even using Flux as a guide. Instead we had to force the project into a Flux pattern we didn't understand and wound up with a mess.

Regardless, I have learned to associated the phrase "best practices" with some imminent cargo culting.


I agree that “getting started” experience is far from optimal. We take this feedback to the heart and want to improve this in the future. But how is this relevant to the post about mixins?


I see it went OT, sorry about that.


Uh... on the contrary, there's a bunch of fairly in-depth tutorials out there. I have a number of them listed at [0] and at [1]. Also, I think a couple of the more commercial courses do that sort of thing as well. Wes Bos's Redux course builds a "Reduxstagram" app or something, Tyler McGinnis's "React.js Program" course builds up a couple specific apps, etc.

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

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


If simple things were possible before with React, then they still are, and that's not changing. You don't need Flux and Redux a lot of the time; in my experience they're overused and React component state is underused.

I agree the community mentality of adding lots of complexity on top is a problem. We're working on improving this, but if you have ideas I'd be interested to hear them too.


> "in my experience they're overused and React component state is underused"

Thank you, I've felt the same way. A lot of projects take "ALL STATE MUST BE IN THE STORE" to an extreme.


Which is funny because you'll never hear that from Dan or any other authors.


ikr


IMO its no more trouble to put state in a redux store than in the component directly and doing so makes my components more consistent. I'm not a react guru though so maybe I'm missing something.


Eh, sometimes state isn't relevant outside of a component, so while you could put it in a store, it's possibly better to put it in the component. Single responsibility.


I bet React programmers who write a Mithril component or two would come back to React with more readiness to use component state. I don't have a plan for how you could use this idea to improve the community, though.

As for the mentality of adding complexity -- are you sure that's a community problem? It seems a problem with programming in general. Advocates of adding complexity tend to be louder than advocates of using what's already there.


I meant "community" as opposed to the official guidance we supply, where we try hard to keep things simple. I know that it's easy to slip into the trap of making things more complex and I don't blame anyone for that mentality winning out.


Just a small point, but React has always had higher order components as long as I've been using it because they're just a subset of higher order functions. It's more of a feature of JavaScript than it is of React. Also, I've been encountering higher order components since I started on React two years ago I think. The definition of what constitutes a higher order component is very broad. I think that any render() method which returns a component would qualify.


That's because people are using it for real things now, not just as a jquery plugin replacement, and it turns out that ignoring hard things doesn't make them go away.


Yup. That's the point. The average frontend app really sucks. Error handling is poor, routing is bad, offline support is non-existent, it's buggy as hell, slow, etc.

Now, not all apps need all of those things to be good, but they usually need some combination of those things. When you start making things "good", they're hard. Peanut Gallery Joe who learnt Rail and JavaScript over the summer jumping in this is not equipped to make a good app, and gets overwhelmed.

Compared to writing "robust" applications in other ecosystems, the React world is really not that bad.


Check out cycle.js. I haven't learned it quite yet but the promises seem really interesting. It's a fully reactive framework unlike react which is reactive only in view.


Cycle is indeed interesting! React is not “fully reactive” by design, and does not plan to move further into the reactive direction. We think that React is well-positioned in the app to understand how to efficiently schedule work instead, which is something that would be harder for us to do with a reactive “push” approach. I think as time goes, it will be interesting to see how both Cycle and React evolve into different directions, and what different tradeoffs they might present and benefit from.


If you haven't looked at it in some time, Cycle.js has just really improved in the last month, an effort the devs are calling "diversity". Under the hood, that means RxJS is no longer a hard dependency, as a bunch of different reactive modules are now usable, including Staltz's new "xstream". Not having looked at Cycle in a few months, I'm not certain what all the particular changes have been, but I'm finding everything just seems simpler and more obvious. Admittedly, I am an RxJS novice, and some of the constructions I saw with that before just confused me.


There has also been some perf work done recently it seems http://www.stefankrause.net/wp/?p=301

I have to look a little closer at the tests to be able to interpret the data but taking it on face value it seems like they are doing good work.


I feel like React is shifting in the same direction as the JavaScript ecosystem at large, which is unnecessarily complex, disorganized, and fast-moving.


Can you help me understand where React is shifting into a complex direction?

To me, it looks like we are no longer recommending a complex pattern that we specifically supported in code (mixins), and instead recommend a simpler pattern that “just works” in JavaScript (higher order functions/components).

If anything, we are shifting to a simpler direction, and it worked better for us. We are sharing the lessons we learned in the hope that you might also find them helpful. Sorry if they’re not!


I think part of it is that not everyone is expert or familiar with functional programming (trained on OOP, etc) and it can feel overwhelming to many. "This is simpler - just another function" is somewhat subjective.


I believe this is exactly why we explain this pattern in the blog post in detail instead of just saying “this is simpler—just another function!”

We are trying to both deliver a library that helps people ship quality apps, share our learnings about what worked, and what didn’t, and educate the community about the patterns that we found useful in our experience.


I agree, mainly addressing the general vibe that React is complex - many folks have a gut knowledge of imperative that they lean on to make snap judgements about complexity, even when you explain it fairly clearly.


If you're building a simple app, keep it simple (but, do you even need React then?). If you're building Facebook, bring on the strong typing and design patterns that facilitate building large javascript applications.


>I believe as time passes, we are moving away from the simplicity that made React win.

Because every framework will handle small simple use-cases beautifully. When you include a codebase with thousands of lines of code, co-developed by many people, you can see where the pain points are.


I think React is moving towards a simpler abstraction. There is nothing simpler than a function with the type Model -> View.


Yup - trying out Elm makes you realize how much complexity is in the React + Redux stack that is not really needed...


Take a look at Reagent (ClojureScript library) for a breath of fresh air and simplicity.


I personally moved all my projects away from mixins a while ago when I first heard they were deprecated. At first I was frustrated because of JS churn but this certainly was the right move.

For anyone who is apprehensive, the shift in thinking from using mixins to HOCs was not so difficult even if it's initially puzzling.

Quick edit: forgot to mention that this shift made my code way easier to understand in some places and thus the initial investment saves dev time in the long run.


I'm a fan of HOCs as well. My only problem with them is that I'm also a fan of shallow testing, and HOCs don't play nicely with shallow testing. I'm waiting on something like this (https://github.com/airbnb/enzyme/issues/250) to get implemented


Export every component like this:

export class MyComponent extends React.Component { ... }

export default SomeHOC(MyComponent)

And in your test simply import the non-hoc version:

import { MyComponent } from './mycomponent'

Now the HOC won't get in the way of your testing.


Why not just mock the HOC to be the identity fn? `(Component) => Component`


This is my preferred approach as well - and it (anecdotally) works great, since you can then just manually inject any props/spies as needed like any other "dumb" component.

Edit: But he might be pointing to the testing of the actual HOCs/component decorating functions.


> I personally moved all my projects away from mixins a while ago when I first heard they were deprecated.

Mixins were actually one of the things that turned me away from React in the first place. Perhaps a good time to reconsider :)

(Are there any other known anti-patterns left in React?)


>Are there any other known anti-patterns left in React?

String refs and `findDOMNode()`. Both are anti-patterns but not deprecated yet. Both replaced by callback refs.


Could you expand on string refs as an anti-pattern?


I wouldn't necessarily call them an anti-pattern, but they are at the very least not encouraged:

> Although string refs are not deprecated, they are considered legacy, and will likely be deprecated at some point in the future. Callback refs are preferred.[1]

I'm still using them in React Native, because I'm new and didn't realise there was an alternative until recently. To me there are three issues:

1. Magic. All you do is specify a string and somehow you end up with this.refs.<name>. Admittedly not that hard to follow, but magic is generally bad.

2. It's hard to keep track of what refs actually exist, which makes naming collisions hard to notice. There's just some arbitrary string in some JSX. Using explicit properties means they can be tracked much more easily e.g. Flow.

3. Again related to Flow, if you're declaring your properties as you should be, then Flow will tell you if swapping a referenced component type (checkbox for switch etc.) is going to cause problems elsewhere in code.

EDIT: I suppose you could already be declaring your refs with Flow. However, if you're doing that you're already 90% the way to using dedicated properties. In which case you might as well eliminate the magic and just use your own properties, rather than properties on refs. This makes searching for usage/references much more obvious; people/IDEs generally don't think of strings being a reference to a variable.

[1] https://facebook.github.io/react/docs/more-about-refs.html


I'd like an answer to this as well. I've only ever needed string refs, and the callback refs are noisy. I can see where the React team may not want to support both, but are string refs actually bad in some way?


String refs are bad in quite a few ways:

1. String refs are not composable. A wrapping component can’t “snoop” on a ref to a child if it already has an existing string ref. On the other hand, callback refs don’t have a single owner, so you can always compose them.

2. String refs don’t work with static analysis like Flow. Flow can’t guess the magic that framework does to make the string ref “appear” on `this.refs`, as well as its type (which could be different). Callback refs are friendlier to static analysis.

3. The owner for a string ref is determined by the currently executing component. This means that with a common “render callback” pattern (e.g. `<DataTable renderRow={this.renderRow} />`), the wrong component will own the ref (it will end up on `DataTable` instead of your component defining `renderRow`).

4. String refs force React to keep track of currently executing component. This is problematic because it makes `react` module stateful, and thus causes weird errors when `react` module is duplicated in the bundle.

This is why we want to move away from them in favor of callback refs that solve all those problems.


I think it's important people understand this. The last two points are precisely the reason String refs got moved from Preact's core into preact-compat.

Also, for the common-case usage of string refs, you can just use a helper to insert things into `this.refs`:

https://gist.github.com/developit/63e7a81a507c368f7fc0898076...


Thanks for the thorough answer, Dan.

(Had I not followed the prescription for the sake of being future-proof, I probably would have had a painful debugging session over #3. And possibly #1 too.)


from the article

> Let’s make it clear that mixins are not technically deprecated. If you use React.createClass(), you may keep using them. We only say that they didn’t work well for us, and so we won’t recommend using them in the future.


I think around React 0.14, they announced that React's support for es6 class syntax wouldn't support mixins, and you'd only be able to get them by using the old .createClass method. I think they pointed out that they didn't see this as a big issue because mixins were a pattern they wanted to get away from anyway and saw better solutions to.


It's funny to see in the life cycle of every new language/framework in the block the rediscovery of good architectural patterns that can be summed up in one sentence: - inheritance & mixin bad / composition good.

Good article nevertheless.


> inheritance & mixin bad / composition good

This wisdom is at least as old as the classic GoF book [1] which was published in 1994. Many of their patterns can be summarized as: "Favor 'object composition' over 'class inheritance'."

They also give a pretty simple, compelling reason for that: It is just a direct consequence of the even more fundamental principle:

"Program to an interface, not an implementation."

[1] Gang of Four (Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides): "Design Patterns: Elements of Reusable Object-Oriented Software" https://en.wikipedia.org/wiki/Design_Patterns


I would argue that the more intuitive principle behind composition is the "Single Responsibility" one. Although it is correlative to the idea of 'program to an interface' (aka don't mingle with the state from the inside of an object that is not for you to do) I find it easier to grasp.

While i'm at it I'll add that the main reason SRP is so important is because it limits combinatorial explosions of state, so you can keep control, test and reason about it - incidentally the main idea behind the success of React.js


I find that inheritence allows me to save a ton of code, but using it widely does mean you need the ability to refactor, which isn't hard in Java or C#, but can be more of a pain in languages like Ruby.


inheritance is very hard to comprehend at a later date, traversing though sub/super class hierarchy, overrides and super calls is incredibly painful.

You often end up with a subclass that may be thousands of lines in length if you consider it's flattened definition.


This hasn't been my experience at all. Most class hierarchies I've seen don't got much further than 2-3 levels deep, and each level deals with a specific level of functionality. In most cases, the last descendant class contains the functionality that the end class "user" is most likely to be interested in, while the ancestor classes are most likely to contain foundation code/data that is primarily used by the descendant classes internally (but not always, of course).

Also, most modern IDE's have a "Find Declaration" or something similar that allows very simple traversal of class hierarchies. And the help systems are built to allow for easy navigation of the hierarchy so that you can visualize the inheritance paths.


That's too bad, mixins were simple to grasp and worked really well. The oft suggested alternative to mixins is higher order components. Here's one of my favorite quotes[0] on the matter:

> You lose so much with [higher order components], especially with es6:

> You lose the (original) class, and with it, the ability to compose it, to extend it and …. reflection. All your components are [the higher order component]. For example, you cannot rely on the Class.name in es6.

> You lose the ability to extend the component and expose extra members. Your higher order component will not ‘pass’ that through.

> The above two basically renders the ability to compose several decoupled and agnostic one to the other “higher level components” impossible.

> It is verbose and non-declarative , and basically much less readable and maintainable.

If there's a better pattern than mixins, I would say its traits[1]. For some reason, I don't find it used much often in the wild. I'm not sure it would be practically applied to React anyway without ending up with mixins again, but at least the concept would be clearer: there should be no shared state and dependencies are explicit.

0. https://medium.com/@danikenan/you-lose-so-much-with-your-sol...

1. https://en.wikipedia.org/wiki/Trait_%28computer_programming%...


>the ability to compose it, to extend it and …. reflection

In our experience those are precisely the things that can turn codebases into a mess. It’s great that you can manage the complexity from inheritance and reflection, but in our experience most people had problems with these patterns (me included). On the other hand, we found that React composition model is enough to express everything we needed in the apps, and we didn’t miss inheritance or reflection.


From the article:

> Let’s make it clear that mixins are not technically deprecated. If you use React.createClass(), you may keep using them. We only say that they didn’t work well for us, and so we won’t recommend using them in the future.


Great post Dan. Just out of curiosity - what's your goto approach for replacing examples like the SetIntervalMixin (https://facebook.github.io/react/docs/reusable-components.ht...) with a HOC? I can't seem to find something that feels very elegant for these cases.


I’d probably create a class that lets me schedule intervals on its instance, and call `this.scheduler.dispose()` in `componentWillUnmount()`. I don’t think accidentally forgetting to dispose of it is a big problem as it’s easy to catch in a code review. But if it concerns you, HOC could work for this as well. In the future, we might build some helpers for this into React itself.


Yup - that's more or less what I've ended up with. Just wanted to hear you if you had a better solution at hand. It's pretty much an edge case example, as 99% of all this stuff fit perfectly into the HOC way of thinking. The remaining cases won't add any more context/complexity than using mixins do anyway.

Thanks for all your hard work!


You could write a pretty trivial component which takes an interval and method as props, and sets the interval in componentDidMount and cancels it in componentWillUnmount.

It probably doesn't make sense to do a timeout that way...


Mixins have their place, but perhaps we are at the point where we need general advice (like the class "Prefer composition over inheritance") for mixins ("Prefer traits over mixins"), especially as there's a good analog between the two. Matthijs Hollemans wrote an article which argues for that as well:

http://matthijshollemans.com/2015/07/22/mixins-and-traits-in...


For those of you complaining about "javascript complexity":

I think one of the biggest misunderstandings about JS and a large portion of the community complaining about "churn rate", is that JS does not have a churn problem, it has an inexperienced developer problem. Which is not to say that is a bad thing, JS/web is the first language for MANY programmers now.

When you get stuck on learning this framework vs that framework, or a antipatterns within a framework and "complexity" being added to a framework, take a look back and understand the WHY first.

Many ideas and the fundamental design of React are not new. Infact, they are very old, even before there was such thing as the internet. Functional programming patterns, also very old. Immutability, a very old concept. Composing rather than inheriting, old concept. Eliminating all side effects (through immutability and composition), very old concept.

The idea of a "higher order component", is not new, nor does it have any direct relation to React. It is a design pattern. This article is simply teaching you a design pattern that aligns with the design patterns React was built upon and works very well. Instead of complaining about React and "added complexity", I encourage you again, to ask why. Learn why this blog post, from the React core team, recommends doing it this way. It is in no way a requirement. React is just a tool. It is just Javascript. It is just programming. Welcome to the development world.

Also, understand the problems you are trying to solve. Facebook uses these design patterns because they have thousands of components at a massive scale. The majority of users will not be working on something of that size. Don't feel like you have to use everything that comes out and is available in the React ecosystem. Infact, I would urge you, never start using something UNTIL you come across a problem and need to find a solution. It is a common thing for inexperienced developers to feel the need to incorporate everything they have read about, when they are using them to "solve" problems they don't understand, nor even have. This applies to problem solving in general, not just React, not just programming.

TL;DR Understand WHY something is used in the way it is before throwing it out as "too complex". Don't solve problems you do not have, until you need to actually solve them. If you do use a pattern/tool/etc., understand the WHY. (Don't use Higher Order Components or redux if you have not had the need for them and do not understand the problem they solve.) Also understand that many design patterns coming to JS are not a result of JS churn, they have been around a long time and have a very good reason for existing. JS churn is not real, it is a misunderstanding of using a solution in a world that has many solutions available.


Thanks for saying this.


0.3 - 0.1 = 0.19999999999999998


Floating point error, present in every language that uses floats. This is in no way unique to JavaScript.


Talk is cheap, give an example in code.


Python REPL:

    >>> 0.3 - 0.1
    0.19999999999999998
Ruby REPL:

       0.3 - 0.1
    => 0.19999999999999998


https://repl.it/Cbqb unless your Python compiler runs on some sort of JavaScript (-:


  Python 2.7.12 (default, Jul  1 2016, 15:12:24) 
  [GCC 5.4.0 20160609] on linux2
  Type "help", "copyright", "credits" or "license" for more information.
  >>> 0.3 - 0.1
0.19999999999999998

Python 3.5.1 yields the same result


I don't use python, but print-like functions(or in this case, statements) usually format their output. https://repl.it/Cbqb/1

From the documentation:

> print evaluates each expression in turn and writes the resulting object to standard output (see below). If an object is not a string, it is first converted to a string using the rules for string conversions.

I can't even find what the rules for string conversions are in the documentation :/ Oddly enough they're not described under https://docs.python.org/2/reference/expressions.html#string-...


And while you're at it, do you know of any other language that does this? http://pasteboard.co/bbM0qneiQ.jpg


"Considered Harmful" Essays Considered Harmful: http://meyerweb.com/eric/comment/chech.html


I don’t think there’s anyone writing Considered Harmful articles who hasn’t ready that essay but thanks! ;-)


I'll likely catch some hell, but there's a reason mixins are considered an anti-pattern in most languages...


Yup, no news here. For people who already know that, this was designed as a post with specific examples that tend to pop up in React codebases and advice about how to migrate away from them.


I worry this suggests an opposition to inheritance in general. Sharing code through class hierarchy is incredibly useful and common. I'd hate for ES6 to add decent classes and then have React push people away from 'extends'. But perhaps I'm reading too much into this.


>I worry this suggests an opposition to inheritance in general. Sharing code through class hierarchy is incredibly useful and common.

This is indeed opposition to inheritance in general, precisely because we tried it, and it doesn’t work great in React apps. React has a strong composition model that does not need inheritance.

https://discuss.reactjs.org/t/best-practices-for-extending-s...

Of course you are free to use inheritance for other purposes. (Or even React components if you insist.) But as the team behind this library, we strongly suggest you to use composition instead of inheritance when defining React components.


I would add that there seems to be a push against inheritance in general with UI components in the frontend web app world. React clearly is designed against using it, and same thing with Angular 2 (inheritance does not play well with decorators, which are metadata on specific component classes). I don't think we really see any modern UI library/framework adopting inheritance as a valid pattern at the component level, precisely due to the problems of leading developers down the path of creating potentially incorrect abstractions & being too painful to fix when UI can potentially change quite a bit structurally.

In addition, anything a user can accomplish with inheritance, a user can also accomplish with composition, but while retaining flexibility, so when considering how much the UI layer can change in an app, one generally wants that flexibility. Inheritance is more useful when creating low level abstractions or maybe wrappers around such, but should generally be avoided when it comes to consumption for higher order constructs because of the complex chains involved.

* This is what I have found at least - perhaps I'm making some incorrect points. If so, I'd like to know why I'm wrong here, since these are just conclusions I've drawn from experience so far.


> I don't think we really see any modern UI library/framework adopting inheritance as a valid pattern at the component level, precisely due to the problems of leading developers down the path of creating potentially incorrect abstractions & being too painful to fix when UI can potentially change quite a bit structurally.

Composition has the exact same problem in this respect.

* Object A

* Object B

* Object C

   * Object A

   * Object B
Object C is composed of Object A and Object B.

Now go and write code that has instances of Object C. Can you remove Object A without side effects? The amount of pain you experience from removing Object A from Object C isn't related to composition or inheritance. It's related to how often you use a particular object. Furthermore, if you're a library author, pain and inflexibility can arise from how API customers react to breaking changes ( badly ). In this case, it really doesn't matter whether or not you're using inheritance or composition.

It amazes me how many programmers cannot seem to understand this.


When people say “composition” they refer to different things. You are referring to object composition.

In React, “composition” means has a very specific meaning: it’s putting components into components. It has very little to do with object composition because in React component instances almost never “talk” to each other. They don’t call methods on each other.

React component model is much closer to functional composition which doesn’t suffer from the drawbacks you describe.


Will using composition help me avoid large, painful refactors if I change the composition of my components?

If I have an object that inherits, I might say:

Object.Func() // Method implemented by base class.

If I have an object that uses composition, I might say:

ObjectA.ObjectB.Funct() // Using method of Object B.

There are dependencies in both cases. Composition simply changes the way the dependencies are distributed across a set of objects.

* Inheritance is getting something from you parents.

* Composition is getting something from your children.

Both are valuable strategies in systems design. It seems to me that your apparent dislike of inheritance is motivated by the fact that it's currently trendy to dislike inheritance, rather than having any rational / well-reasoned technical motivation.


I don't think you've really read and understood the notion of function composition. All you're talking about here is having objects as properties of other objects - that is not function composition.


I'm not asking about function composition, I'm asking if there is any basis for disliking inheritance other than the fact that it is currently trendy to do so.


There’s something I’d like to clarify.

The article you are commenting on is about avoiding mixins in React components. It is not a general statement saying “Always use anything called ‘composition’ over anything called ‘inheritance’”.

We found that inheritance doesn’t work well for React components. And we found that composing React components with React’s composition model (which has very little to do with object composition) worked well for us.

Nowhere do we claim that object composition is better than object inheritance, or something else generic like this.

(Sorry if you didn’t interpret it this way. I just want to make it clear for future readers that this branch of discussion is not related to the contents of the article.)


Currently trendy?

https://en.wikipedia.org/wiki/Design_Patterns#Introduction.2...

I wouldn't consider 1995 current. And it's gone way beyond "trendy".

EDIT: Also, what you've mentioned there is not composition - it is objects that have other objects as properties. Composition basically involves wrapping and forwarding, whether it's function or object composition.


This is incredibly unfortunate. I feel like this attitude will turn off and hamper a lot of potential users. It smacks of functional proselytizing and it is not appreciated.


We are sharing what worked for us. Why would be encouraging people to use patterns that did not work well for us?


I totally agree. Upvoted!


Why not just prototype inheritance with multiple inheritance? Like Self. The class-instance duality is removed then, and everything is just an editable object. This always made the most sense to me. Then just having the 'universe' be a map of id->obj with prototype inheritance, then editing the universe being reduxy and just a reduce over the objects, with the reduce polymorphised over the object's inheritance (this is the benefit of OO, really, not mutable update)--brings wins of functional, prototype, OO all together.


It's not clear to me why (in the pattern presented) the decorators don't return a subclass (which would preserve the dynamic and static properties and methods, etc). Instead you get hacks like `hoist-non-react-statics` to copy them over manually.

For context, the article advocates the following:

    import GlobalClass from 'global-class'

    const decorator = SuperClass =>
        class extends GlobalClass {

            render() {
                return <SuperClass {...etc}></SuperClass>
            }

        }
This can be rewritten to remove the fixed dependency on `GlobalClass`, while preserving the underlying type:

    const decorator = SuperClass =>
        class extends SuperClass {

            render() {
                // const SuperClass = super.constructor // if you want to be less explicit...
                return <SuperClass {...etc}></SuperClass>
            }

        }
The only requirement is to maintain the contract outlined by the `SuperClass`, but that's what `super` is for. (By that I mean e.g. that `componentDidMount` should't be overwritten without also calling super.componentDidMount() before/after).

Returning a different kind class entirely limits the utility of the pattern in general (IMO), and you lose the nice function-composition-like behaviour provided by `super.method`.


In our experience inheritance causes a lot of hard-to-find issues, and muddles boundaries between component concerns. Some of the same problems I described we had in mixins also apply to inheritance.

>and you lose the nice function-composition-like behaviour provided by `super.method`.

We found this to be an anti-pattern. It’s easy to get lost in virtual calls across hierarchy, and people are going to create virtual methods (and override them) if you allow it.

>Instead you get hacks like `hoist-non-react-statics` to copy them over manually.

An alternative is to just not put static methods on component. It’s not such a useful feature.


But mixins are so easy and are used in thousands of JavaScript libraries. Seems odd to deprecate their usage in React; why wouldn't you embrace a typically used construct in JavaScript? The syntax without mixins just seems overly complex. I mean sure it's still simple but more complicated than before and certainly not intuitive (in my opinion anyway).

I just started exploring React not long ago. It's interesting but I'm not sure it's my cup of tea just yet but most of the issues mentioned exist everywhere with JavaScript because, well, it's a dynamic language. I would suspect many of the issues lie outside of using mixins and more of how everything is architected but without seeing their codebase I don't actually know that. I just know mixins can be used, relatively easy, and cleanly as long as your design is appropriate for them.


>Seems odd to deprecate their usage in React; why wouldn't you embrace a typically used construct in JavaScript?

Because we already did embrace it, and we found that it was a mistake.

I believe that the article addresses why mixins didn’t scale well in our React codebases. We have written a ton of React code and wanted to share our experience.

It seems quite normal to me that our experience might not match experience of other JavaScript users. React offers a component model based on functional composition solution that was not quite common in JavaScript until very recently. Paradigms are much more fundamental than languages. We found that, with React’s paradigm, in our experience, mixins were unnecessary. For sure, your mileage may vary.

>most of the issues mentioned exist everywhere with JavaScript because, well, it's a dynamic language

You might not believe me, but these issues had much less of an impact on us with React’s component model. And even less so after we started using gradual static typing with Flow (http://flowtype.org/).

>I would suspect many of the issues lie outside of using mixins and more of how everything is architected but without seeing their codebase I don't actually know that.

I have been employed by Facebook for just a few months. I have written a few relatively complex React apps myself before. I didn’t see much of a difference between the mixins I wrote previously and mixins I saw at Facebook. In my view, both mixins I wrote and mixins I saw at Facebook introduced similar problems to the respective codebases.

It’s great that you know how to use mixins without shooting yourself in the foot. This is a rare gift in my experience. Most people (like me) will overuse them because they’re too powerful. On the other hand, components are limiting enough that even people like me can write code that is easy to maintain in the long term.

>The syntax without mixins just seems overly complex. I mean sure it's still simple but more complicated than before.

What syntax are you referring to? I don’t think there was any new syntax in the article. The only challenging part might be the idea of a higher-order component, but this is not even a React feature. It’s the way JavaScript works: you can create functions and pass arguments to them. It turns out that we could solve one of the use cases for mixins with vanilla JavaScript constructs and without the need for a complex mixin system.

I think you might be missing the point that we have seen quite a bit of React apps being developed. Some of the things we say might be counter-intuitive but they come from Facebook’s extensive experience of using React (more than 20,000 components). So when we’re saying something, it is not theoretical or out of spite. We are trying to share our experience with you, in the hope that you might find it useful not to repeat our mistakes.


React dropping mixins is the #1 reason why I stopped using Meteor. Sure Meteor has Blaze, but nobody uses it.

Before we had a nice mixin called getMeteorData:

``` var HelloUser = React.createClass({ mixins: [ReactMeteorData], getMeteorData() { return { currentUser: Meteor.user() }; }, render() { return <span>Hello {this.data.currentUser.username}!</span>; } }); ```

Short, simple, you knew exactly what it was doing without breaking your wrists.

Now it's some create container lunacy that brings no benefit to most projects except dogma "properness" - the developer UX is just fungled beyond belief and it makes me so sad that Meteor lost so much.

I guess my gripe in general with Javascript now is how complicated simple things are. It's entire ecosystem is intertwined with complexity and verbosity.

I wonder if typescript alleviates some of these pain points.


I was going to sketch out a higher order component for you that does the same thing but it looks like they've already implemented that: https://atmospherejs.com/meteor/react-meteor-data

I guess this is the "create container lunacy" you're talking about?

I'm not sure what's so horrible about it, especially if you enable decorators in Babel (admittedly non-standard syntax but it works great):

    @createContainer(() => ({
        currentUser: Meteor.user()
    }))
    export default class Foo extends Component {
         return <span>Hello {this.props.data.currentUser.username}!</span>;
    }
This is basically how Redux's React bindings works too.

Is it really just the syntax you're upset about, or am I missing something?


You don’t even need that syntax. (Please don’t use decorators in examples, they are not part of the language yet. This is super confusing.)

    function Foo(props) {
      return <span>Hello {props.data.currentUser.username}!</span>;
    }

    function getMeteorData() {
      return {
        currentUser: Meteor.user()
      };
    }

    export default createContainer(getMeteorData)(Foo)
Why do you see this as “lunacy” compared to mixins?


> I wonder if typescript alleviates some of these pain points.

TS :> JS, not <:. What specifically are you hoping TS addresses?


Seems to be that the harmful part of the code is actually the OOP. The solution they provide is not a direct attack vs mixins (composition, multiple inheritance), instead they propose to use functions instead of methods but keeping the root of the problems (methods), they may notice in the future that the classes will bring the same issues (the parent can also have a method with the same name...). Notice that the key solution is to use functions (pure, deterministic). While react is a good improvement to remove states, it still promotes objects that are still holding states. I hope they can get more advise from their haxl team :)


I kindddd of feel this way about the "global" context as well, but it's one of those sketchy-yet-handy things haha. Though beyond react-router and redux using it I haven't touched it personally.


I will fight hard to never use globals or Singleton's. It makes my code conceptually way more obvious but sometimes the boilerplate is just wild to pass things like eventemitter around


I thought this was pretty well known by now, given the lack of mixin support in ES6 React components (and functional stateless components), but this is a nice summary of the problems and solutions.


So there are a lot of features in React that are basically getting deprecated, like createClass in favor of ES6 components, mixins, etc. This is good that you guys are learning as you go, my question is will you ever release a version of React, possibly spin React off into a version which supports deprecated APIs and a version that doesn't and is therefore smaller, faster, and easier to maintain? Eventually you could drop support entirely for the deprecated feature. That would be the best response to this IMO.


We are not deprecating `createClass()` yet.

When we do, we will keep it for another major version (just like we always approached deprecations) and then move it to a separate package so only people who really want it would use it.


Yeah I was just using createClass as an example of a feature that's not strictly necessary and could be removed to slim up the library. Thanks for responding! Any idea when you will be trimming stuff like that out? Do you think you will you ever remove mixins?


We don't need to remove mixins because that's one of the biggest reasons people use createClass(). So it's enough to just separate createClass() and then we wash our hands, and it lives its own life. We won't use it but others are free to if they like it.

No specific timeline but we might I'd say within half a year is likely.


Racket has classes as first-class values. So a mixin is a function from one class to another. This seems similar to higher order components solution. https://docs.racket-lang.org/guide/classes.html?q=mixin#%28t...


Similar but the big difference is the wrapping component does not extend the wrapped component. It uses React component model for composition.


I see some React code using decorators but this article doesn't mention them. I'd love to get everyone's opinion on whether decorators are also an anti-pattern, even if decorators become a JavaScript standard.


Since they are not part of the standard, we are not going to take a stance on them yet. We do, however, think that it is very risky to adopt experimental language features unless they are very simple (like object spread operator). In my personal experience people often misunderstand how decorators work, and the tooling often breaks, so I would not recommend them with React yet.


The higher order function example in ES6:

https://jsfiddle.net/jpsierens/obgh1uc7/2/


Apparently React is already moving from "Technology X will solve all problems" to "Technology X considered harmful" pattern.


From my extensive experience using Backbone, Angular, and now React:

React and SPAs Considered Harmful

I keep seeing dependency bloat, over-engineering, unnecessary complexity, all with SPAs not providing the basic things Django/Flask do easily. A good explanation here:

https://medium.com/@wob/the-sad-state-of-web-development-160...

If you're going to use React, use it on one page don't make your whole site/app a single page app.


It doesn't fare well that a framework that is only 3 years old already has an extensive list of anti-patterns and tons of statements on what not to do. Also having to do manual performance optimizations using the framework is a hassle to application developers and can be a major pitfall (ex. PureRenderMixin, shouldComponentUpdate).


>It doesn't fare well that a framework that is only 3 years old already has an extensive list of anti-patterns and tons of statements on what not to do.

Doesn’t programming in general have solutions that scale well, and solutions that don’t scale well? Would you rather not have people writing about their experiences because it “doesn’t fare well”?

We are just sharing some things that worked well for us, and some things that didn’t. Things that didn’t (mixins) will eventually be forgotten as we move away from those APIs. So it looks like progress to me, but maybe I misunderstand something.

>Also having to do manual performance optimizations using the framework is a hassle to application developers and can be a major pitfall

You don’t “have to” do those optimizations. We only use them in about one in twenty components. But they are handy, and having an option to speed up a component with a few lines is better than having no such option. What do you think?


A corollary to what I'm saying is that the design patterns that are espoused by React authors can be eliminated by using another abstraction, they're specific to React and have nothing to do with programming in general. I wouldn't go so far as to say, never use mixins in JavaScript, for example.

>You don’t “have to” do those optimizations.

Sure, but it seems to be a trade off of complexity for user experience. It's just covering up a leaky abstraction.


>they're specific to React and have nothing to do with programming in general

Higher-order functions are extremely common and useful in all functional languages. In fact many people gave us the exact opposite feedback: React taught them many functional programming patterns that they later used elsewhere, both with and without JavaScript, not to say React.

>I wouldn't go so far as to say, never use mixins in JavaScript, for example.

This is not what the article says. There is a paragraph clarifying this specific point, as the sibling comment points out. And the article is sprinkled with “in React codebases” and “in our experience” for this very reason.

>Sure, but it seems to be a trade off of complexity for user experience.

I don’t understand what you mean. In most cases you don’t need to do anything, React is fast. When you have an especially complex tree (not very common), you can add three lines to a few files, and React is even faster. It is a tradeoff, and it is a pretty damn good tradeoff in my experience working on React apps. What am I missing?


>Higher-order functions are extremely common and useful in all functional languages.

Yes but higher order components as you call them, seem to be an abstraction that you would only use because the base unit of organization is a React component. I'm of the opinion that design patterns emerge due to deficiencies in the language or abstraction level, and that they can be avoided.


>Yes but higher order components as you call them, seem to be an abstraction that you would only use because the base unit of organization is a React component.

I don’t really see the issue here. “How do you parameterize Y by X?” “Create a function that takes X and returns Y.” Doesn’t really seem React-specific.

The unit of organization is indeed the component. Again, I’m not sure I understand why it being a first-class thing indicates a deficiency. By this logic, functions are deficient in JavaScript because you can pass a function to [].map(), or Promises are deficient because you can resolve() a Promise to another Promise.

I think the opposite is true. The abstractions are more powerful when they afford building higher level abstractions on top of them. Obviously you shouldn’t overuse this, just like you shouldn’t overuse higher order functions, but it’s a nice property to have.


>“How do you parameterize Y by X?” “Create a function that takes X and returns Y.” Doesn’t really seem React-specific.

I'm not talking about the what, but why would anyone think of using higher order functions to build user interfaces in the first place. It complicates the use case: building and mutating DOM Nodes.

>I think the opposite is true. The abstractions are more powerful when they afford building higher level abstractions on top of them.

And what may I ask requires so much power for building web front-ends?


>I'm not talking about the what, but why would anyone think of using higher order functions to build user interfaces in the first place. It complicates the use case: building and mutating DOM Nodes.

Why are you using a higher order function to `[].filter()` an array? It complicates the use case: iterating over items.

>And what may I ask requires so much power for building web front-ends?

I don’t know what kind of apps you are building, but use cases for React at Facebook are very complex. You may create an Ads account and go through the ad campaign creation flow to see what I mean.


Higher order functions are not such a complicated concept. Just a function passed to a function.

You use functions, right?


Yes, but why is the question. I think that is seriously not given much thought and people just accept man-made complexity as essential. It seems tautological to say that higher order components extend components, but it is only due to the design decisions of the React authors that application code must fit its own paradigm, not the other way around.


On the contrary, it's about reducing complexity. You don't have to worry about mixins, classes, prototypes, inhertiance. Just plain old functions. Can't get simpler than that.


> they're specific to React and have nothing to do with programming in general.

I can't think of a single design pattern used in React that isn't a highly common design pattern in any number of languages.

HOC's are just a React implementation of Higher-order Functions.

> I wouldn't go so far as to say, never use mixins in JavaScript, for example.

Neither did they...

This doesn’t mean that mixins themselves are bad. People successfully employ them in different languages and paradigms, including some functional languages... Nevertheless, we think that mixins are unnecessary and problematic in React codebases.


No, no, no. This is exactly what makes React so great compared to Angular (to pick one). There's One Way™ to do things correctly. Using anti-pattern "hacks" will work for a little bit, but in the long run come back to bite you as your software grows and scales.

I've been using React for over 2 years now, and still refer back to that list when I feel like something isn't right.


Huh? This sounds like it's more true of Angular than React - there is a widely adopted style guide, and well-known anti-patterns are very established. I don't get that impression with React.


As a former Angular 1 user I have to disagree with you. There are many many ways of writing Angular apps and the community generally disagrees on what the best ideas are.

Compare this to how people write React components, they all look pretty much the same no matter what application you are working on. Sure there has been some churn, but there are tons of helpful warnings when they have happened and the migrations are easy. The community is also on the same exact page when it comes to writing components.

Outside of components there's a lack of the same cohesiveness with competing architectures. But the good ideas are rising to the top and the bad ones are fizzling away. I don't see it as a bad thing.


I added "to pick one" because I don't particularly want to start a flame thread over frameworks. Everyone can choose their own tools for their jobs.

However, to the point about style guide/anti-patterns: I guess we haven't been working in the same codebases.. I've worked on a handful of different projects and most have scope flying all of the place, with controllers and directives used interchangeably (not to mention factories/services/providers). But really my biggest gripe is the amount of logic that ends up in disparate HTML attributes. JSX is a much cleaner solution.


Well, I commented mainly because of this

> There's One Way™ to do things correctly. Using anti-pattern "hacks" will work for a little bit, but in the long run come back to bite you as your software grows and scales.

This is true, but in the given context that this is not true in the Angular world, that is definitely false. Some of the things you've mentioned are considered known abuses/anti-patterns/etc.


I'd consider large parts of the Angular 1 framework to be anti-patterns. I believe that's the reason why they completely remade the framework with Angular 2, to avoid all these pitfalls. Given that, I find it the complaint that React is doing the same odd :)


I love React, but once you move beyond toy applications it's definitely not always clear what the "one way to do things correctly" is. This is even more true when you start talking about the rest of the ecosystem (testing? build tools? style? Redux?).

I sometimes wish for an opinionated framework that's built around React and possibly Redux (that said, I have pretty strong opinions so there would have to be significant overlap)

That said, I never got deep enough into Angular to know whether React is better or worse in that respect.


As performance optimization goes, I've never seen a system for building apps where you never need to worry about performance. Our goal with React is to give good performance most of the time and to make it easy to optimize when you have problems -- in many cases, by adding a single shouldComponentUpdate. I think we generally succeed at this goal.


Just try using it already. Or any virtual DOM library. You have cosmetic complaints about things that no one who uses this stuff is bothered by.


I don't understand. For any framework there are lots of things that you shouldn't do. Are you complaining that these things exist, or that they're documented? Surely it's better to have them documented.


The "anti-pattern" patterns that you can use to build your React app are usually the "imperative escape hatches" the post is referring to.

They are part of the framework to allow developers not familiar with functional and declarative ways of doing things to get stuff done

I believe its part of the React team's long-term goal to educate framework adopters about the proper patterns and to slowly phase out these escape hatches.


It is indeed a part of our strategy. We can’t just tell everyone to go functional. We are making mistakes and learning together with our users, and we are phasing our patterns when we are confident that the better patterns are accessible and we see that people can use them efficiently without extensive training.


You have to consider that react was the first (popular) implementation of a virtual dom. We learned a tremendous amount how to implement and use the virtual dom in the mean time. And react isn't a framework, it only implements the view layer.


Does that mean the LinkedStateMixin is going away?


Yes, eventually.


So uh, HOC's are basically monads. Right?


I think the intuition might be a little bit related but AFAIK monad is a very specific thing (can “lift” something and map functions over it, or at least that’s what I remember from a monad tutorial), and HOCs are different (they just wrap components). “Decorator” might be a closer pattern.

I would say HOC is more like a regular higher order function... which is why it’s called this way. :P


I agree, a "higher order component" just isn't a monad. A HOC is just good old fashioned object composition. I think you are right to call it the decorator pattern. It annoys me how React ,and in general the entire javascript ecosystem, reinvents the wheel, then gives their invention another name.


It’s not quite object composition though. We are not forwarding any method calls or containing the instances. HOCs are much closer to functional composition than to object composition.


No no, just higher order functions. They don't have join and return.


Coming from ember 1.x, mixins are pure evil


I ported my app from React to Vue in 2 days. Couldn't be happier


That sounds great. Evan put a lot of effort in Vue, and it’s satisfying to see it paying off! While this is very tangential to the article, could you elaborate on what you struggled with in React? We are always looking out for things we could improve.


Did facebook just rediscover that mixins are an anti-pattern? I would have expected them to know that going in, figured they had just thought it was fine as long as they convinced people to use them very sparingly


No we've known and said it for a long time but not very loudly. People haven't used them sparingly and they tend to infect a codebase. Now we're just making a more concerted effort to communicate more broadly that they can be bad.


Thanks for replying -- I assume in whatever planning/architecture meetings went on before react was released that this was a measured decision you all chose to take, weighing the potential dangers less dangerous than the initial usefulness. Is this assumption correct?

If you could do it again, would you leave in mixins or would you keep them out?


It was the right decision at the time - it made React much more familiar for people at FB who were writing PHP/Hack (Dan called this familiarity out in the post). It also enabled some great things that are still awkward with other patterns - https://github.com/reactjs/react-timer-mixin/issues/4 is an interesting case. That functionality is nice and elegant with mixins but not so with classes.

I think if we had to do it again (and get to keep the knowledge of the last few years), we'd probably skip mixins. We'd surely do some other things differently too though :)




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

Search: