6 ms·
Implementing mixins correctly in JS (which React does not) is already a well explored problem space. I like https://leanpub.com/javascript-spessore https://lea
by bcherny 10y ago
Implementing mixins correctly in JS (which React does not) is already a well explored problem space.
I like https://leanpub.com/javascript-spessore 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.
- danabramov 10y agoSure, 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.
- bcherny 10y agoThe 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.
- spicyj 10y agoCan you outline the biggest problems with React's mixins? I haven't heard this complaint before.
- bcherny 10y agoI'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.
- braythwayt 10y agoThank 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 http://leanpub.com/javascript-spessore/c/hackernews
- bcherny 10y agoWow! 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!