top | item 10424135

Khan Academy's React style guide

128 points| mdp | 10 years ago |github.com | reply

74 comments

order
[+] unoti|10 years ago|reply
I've been working on learning React, and finding it particularly difficult. It appears there are a large number of things I need to have in place and pieces of knowledge I need before I can use it. These include some kind of Js compilation step like Webpack or Browserfy, something like Babel, a knowledge of how to use ES6, an understanding of React, and an understanding of how to use React-Router.

Although I've done some Javascript on the front end, I haven't done the other things I mentioned. The tutorials all seem to assume I know how to do everything but one little piece of detail, and I'm finding it difficult to bite on the elephant. It's hard to tell where to start on learning this stuff, and how much I need to learn before I can use it.

Any suggestions for what resources and approach to use to learn react? My goal eventually is an app that runs in 3 versions: web, iOS, android. I don't intend to use javascript on the server.

[+] samstokes|10 years ago|reply
I found this tutorial a very good solution to the problem you describe:

http://teropa.info/blog/2015/09/10/full-stack-redux-tutorial...

It assumes very little and builds an app from the ground up, including configuring Webpack, Babel, react-router etc, explaining what it's doing along the way.

It does use Javascript for the server, but it's well abstracted so it's clear where to swap out the server if needed. (I actually skipped over the server part of the tutorial on the first run through and it didn't hurt my comprehension.)

[+] insin|10 years ago|reply
Start with an HTML boilerplate which takes care of the details of transpiling (which are initially irrelevant to you in learning mode). My first react app started out in a file like this [1] and I didn't go and figure out how to set up a build or use ES6 features until I was > 1000 lines into it, with a working prototype.

If you have an idea for something you want to build as a learning experience, following the same flow as Thinking In React [2] is a good way to get started, using the docs as a reference as you start to explore each area.

- Start by writing a single component which implements render() to get a feel for using JSX.

- Then pass some props into it to get a feel for working with those and interpolating JS using {}.

- Then create a second component and use it from the first component's render() via JSX.

- Once you've done that, you should have enough knowledge to create a static prototype of whatever you want to build while learning and you can play about with componentisation as you go.

- Once you have a static prototype, you can start to learn about state and pass callbacks to child components when they need to update state held somewhere above them.

Just do the simplest thing to get it working until you understand what's going on with props and state. Don't jump straight into React Router, as you'd be missing a chance to learn about, for example, state (to control the current page), conditional rendering (to display whatever should be the current page component based on state) and component lifecycle hooks (to register a basic hashchange event handler to implement your own simple back/forward support). Don't jump straight into Redux, Flux or a cursor implementation, as you won't get a chance to experience the problems they solve first-hand. Build up your app's complexity gradually and come back to these things later once you feel like you have a handle on things.

[1] https://gist.github.com/insin/9c0712cef6ac8583b742#file-reac...

[2] http://facebook.github.io/react/docs/thinking-in-react.html

[+] dominotw|10 years ago|reply
>and an understanding of how to use React-Router.

Gosh no. You don't need react router for simple applications.

[+] metral|10 years ago|reply
I'll start off by stating that I am not a frontend dev, but I've been trying to learn React to connect it to a backend API and I too find it difficult for the same reasons you stated plus some others:

- The FB React docs are a bit scattered in terms of content and not as intuitive / helpful for a beginner as I'd hope they be

- I often resort to referencing other people's code from Github, StackOverflow & Google and the mix of ES5,6 & 7 styling used is hard to wrap my head around, especially when I try to find a source of "truth" on how to adopt the more idiomatic way of doing things seeing how everyone is using a different version from docs to examples

- React-Router's docs & code samples vary widely from what they state in the repo vs what people are actually using, and the whole pre 1.0 / post 1.0 way of using it has bitten me more times than I care to count - this is most likely me jumping in at a transformative time in the project

- Learning tools like webpack, browserify, babel, gulp etc. have been nothing short of a learning curve and these tools are basically required to be useful in React without repeating yourself from running commands over & over again when developing

- I've learned Flux's architecture, understand the concept, have integrated its structure into my code and know that this is the proper decoupling required, but its definitely not been an easy process for me to have to think about how I need to modify the flux pipeline for new functionality and how I can cut down on repetitive code.

- I don't understand how to manage state properly when I navigate to another page - this creates issues for me around the combination of flux + react-router as my lack of experience with them as well as lack of proper examples to utilize make the two difficult to address some of the state management issues I encounter. i.e. If a user logs in & they have a token, do I make use of local storage, do I not, how do I navigate to another page seamlessly with information I want to pre-specify such as the fact that a user is logged in and some of their basic info so I dont have to hit an API etc.

- Lastly, I fear committing to an all-in javascript-dependent solution for a frontend will segment users in terms of it working or not - see http://maketea.co.uk/2014/03/05/building-robust-web-apps-wit... for the tidbit about how SquareSpace's page is completely blank if javascript is disabled - this worries me that I may have a user that can't even interact with my page either because they disabled javascript, or because their browser is outdated/lacks expected functionality.

I know most of these issues stem from my lack of exposure and knowledge in this frontend endeavour. Nevertheless, I have to assume others are getting bit by many of the same issues as well and I constantly question if I'm biting off more than I can chew with React, as well as if I should just go back to the more traditional way of doing things on the server-side which I happen to know & understand already.

/rant

[+] andreasklinger|10 years ago|reply
Request for comment:

Linters are by far powerful enough by now.

Can we (as community) switch to documenting style guides as linter rulesets + custom linters. Eg for javascript: eslint and jscs

Written style guides are good for understanding why - but linters actually help others to adapt to it quicker

[+] greg5green|10 years ago|reply
AirBnB has a similar style guide for React and has a linter file for eslint with the React plugin. Works pretty well.

I'd like to see more style guides come with similar set ups.

[+] deanclatworthy|10 years ago|reply
Couldn't agree more. And you should in theory be able to generate a style guide document from a linter. I know you can do it for CSS
[+] iamjs|10 years ago|reply
It's probably a good time to start looking at using the Fetch API [1] for making AJAX requests instead of using jQuery or Backbone (or even XMLHttpRequest). Support seems to be growing quickly and Github's polyfill [2] can help cover the gaps.

[1] https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API [2] https://github.com/github/fetch

[+] tracker1|10 years ago|reply
Agreed... I really have come to like fetch, though I usually wrap it in a couple functions for my most common use cases... since some of the options are a little tedious to specify over and over again... such as `postJson(url, data)` which will post the data as json, and resolve the json response with some extra error handling.

It works well, and combined with babel for async/await, the workflow is pretty smooth as well.

[+] PhrosTT|10 years ago|reply
Yes, EXCEPT, As of now fetch has no abort() support.

Having 50 in flight autocomplete requests going in parallel is not cool.

[+] tzury|10 years ago|reply
John Resig (jQuery creator) is one of the chief architects at there, and yet you see, this line:

    Never use jQuery for DOM manipulation
Nice.
[+] doppel|10 years ago|reply
I think the implication is not that jQuery is bad for DOM manipulation, but that you should leave DOM manipulation to React to have a 1:1 relation between the held state in React and the actual DOM. In other words: Do not manipulate the DOM outside of React.
[+] albertoleal|10 years ago|reply
This is a React style guide; which implies that React does all (if not, most) of the DOM manipulations for you. jQuery, as a library, have useful utilities that that do not do DOM manipulations.
[+] Cshelton|10 years ago|reply
React keeps all of the "DOM" stuff in memory. Thus it is inefficient and unnecessary to use jQuery to do anything to the DOM.
[+] pramodliv1|10 years ago|reply
A couple of questions:

>Do not use Backbone models

I use Backbone models for ajax since it makes decisions such as PUT vs POST and model.save() looks cleaner than $.ajax. Also, Backbone collections provide a declarative way to handle sorting and duplicate models. But these models are internal to the Store and not exposed to the views. I'm still a React newbie. Is this a valid reason to continue using Backbone?

2. It seems as though Khan Academy do not use React for SVG elements in their interactive exercises. For example, https://www.khanacademy.org/math/geometry/transformations/hs... Do you plan to migrate SVG to React?

[+] ariabuckles|10 years ago|reply
1. If you're not passing the backbone models to React components, this sounds fine. backbone models as props ends up being really painful because of how mutable they are, and when we tried to manage that with mixins, it was buggy and caused problems (note: I'm not familiar with the actual mixin we used there and whether there was a better way to do it). Since most flux implementations are pretty stateful/mutable themselves, using mutable backbone models there, so long as you copy data out to pass to react views, seems safe. Though I'm excited long-term about the immutable flux implementations (https://github.com/rackt/redux)

2. We had a library originally written by Ben Alpert (now core react team) that handles all of our interactive svgs [1]. Since KA has a lot of legacy code there, and there hasn't been an immediate benefit to porting it (which would take a pretty significant time investment, on the [very roughly] order of a couple dev-months), this is still mutable jQuery/raphael code. There have been a lot of talks of eventually porting this to react, but the immediate need for it hasn't been there yet. However, I did write a React wrapper around much of this code which is used by newer interactive widgets [2].

[1]: https://github.com/Khan/khan-exercises/blob/master/utils/gra...

[2]: https://github.com/Khan/perseus/blob/master/src/components/g...

[+] dustingetz|10 years ago|reply
Its a good and common question. Backbone can handle rectangular models okay. When you get into more complicated UI states, or if you have two different views backed by the same ui state like here [1], backbone models totally fall apart - backbone model is designed for list-of-records where the list can change or a record can change, it can't elegantly handle other shapes, like nested records, or list-of-lists, or tree-like (recursive comments), whatever arbitrary shape most naturally models the domain.

Backbone models are also mutable which means lots of model change listeners (callback soup) - check out the flame charts here [2] to get an intuition for what callback soup does to your code and how react fixes it.

[1] http://wingspan.github.io/wingspan-forms/examples/faceted-se... (json blob is the ui state) [2] http://swannodette.github.io/2013/12/17/the-future-of-javasc...

[+] gravity13|10 years ago|reply
I would argue that's fair. Somebody might come along and suggest you GraphQL all the things, but the flux-flavors mostly tend to be focused more on the use of state in applications and less so across the wire. And Backbone's collection/model is pretty good at that.

I can see argument against adding heft to your app, though - if that's something you're worried about. There's the ampersand library which tries to be more modular while reflecting the good parts of Backbone, but it seems to be going a bit quiet.

[+] seivan|10 years ago|reply
Hmm, that's not a bad idea actually. So you never expose your models at all to your components?

Apart from dirty-check for POST/PUT and uniqueness/sorting what other benefits could Backbone models have?

How do you expose your models to the view, I would guess you just serialise into regular objects?

[+] cnp|10 years ago|reply
I'm curious why the top is preferred over the bottom:

Open elements on the same line.

The 80-character line limit is a bit tight, so we opt to conserve the extra 4.

Yes:

  return <div>
    ...
  </div>;
No:

  // "div" is not on the same line as "return"
  return ( 
    <div>
      ...
    </div>
  );
The latter I feel is much more readable and clear than the former, as it has a certain symmetry and cohesion that you find in normal html. The top one seems to be break readability. Wondering if anyone can comment on this specific decision?
[+] xanderjanz|10 years ago|reply
Their logic is that because elements are typically deeply nested, it's better to sacrifice the readability for the saved indentation. By the time you get 4 child elements deep, almost half your line space goes to tabs.
[+] traviswingo|10 years ago|reply
I find it funny seeing this section:

https://github.com/Khan/style-guides/blob/master/style/react...

Even though John Resig is one of their main devs.

[+] mikegirouard|10 years ago|reply
I thought so too. I guess this is a good time to remind ourselves that we are not our work and it's best not to be too attached to the things we create.

It's worth noting however that the heading says to minimize jQuery and more specifically jQuery plugins. My guess is that jQuery is fine as long as it's serving a low-level function (XHR, etc).

[+] aaronkrolik|10 years ago|reply
Style question re dom manipulation: third party embeds, such as twitter, instagram often come as specially classed blockquote elements that are swapped with iframes by a jquery plugin. What is the best way to integrate this with react?
[+] codingdave|10 years ago|reply
"Fit them all on the same line if you can." (HTML Properties) -- OK, easy enough, my editor has no limit on its line length. I can always fit them on one line. Or did they expect it to fit on one line visually. If so, at what width to they expect my editor window to be?

In all seriousness, though, I appreciate the brevity of this guide. It can be quickly read and understood, and is not the fully-fledged book I've seen from other places.

[+] liquidise|10 years ago|reply
A number of these guidelines reinforce my biggest complaint with React: it is architecturally difficult to avoid monolithic view files.

In a traditional web app, we have 4 layers: client views, client app, server app, database. React, described as a strict view layer, in reality is being used as much more. At this point, it is not just consuming the client app, but is also taking nibbles at the server app as well.

To each their own of course, but i would ask people to hesitate about these decisions. The architectural issues with monolithic views is well known, and just because we have a shiny new tool does not mean we should throw that understanding by the wayside.

Source: i work full-time on a React and Backbone app

[+] smrq|10 years ago|reply
Can you explain what you mean a bit more? My experience with React is that composing components is so trivial (particularly compared to e.g. Angular directives) that I've tended to end up with very small view files (~10 lines of DOM max, plus whatever functionality is directly tied to that). It's seemed like one of React's greatest strengths to me, so I'm curious as to where your complaint stems from.

(I don't use React in my day job... yet. But I'm considering pushing for it, so getting a better understanding of its shortcomings is really important to me.)

[+] tracker1|10 years ago|reply
What do you mean by monolithic view files? It's pretty easy to separate at logic boundaries into smaller components...

As for universal rendering, using the same view engine on both the server and client makes sense. Not only that, but being able to use the same routing engine for client and server rendering, especially on a public facing application is a pretty nice thing as well.

[+] Offler|10 years ago|reply
It sounds to me like you are doing React development incorrectly. You should aim to break down your mockups into small components, preferably stateless components (introduced in React 0.14) and only have the higher level components act as wrappers that pass down data into the small stateless component leafs (which should be the majority of your UI).
[+] twsted|10 years ago|reply
"Do not use Backbone models."

This seems a little strong. What is the reason for this guideline? I know of many projects that are combining the use of React with Backbone.

[+] dangoor|10 years ago|reply
We're trying to reduce the amount of JavaScript on our pages and have decided at this point to move forward with Redux as our common approach to state (keeping an eye on things like Relay and Falcor as we move along).
[+] greg5green|10 years ago|reply

  We are trying to remove Backbone from our codebase entirely.
This is more of a guideline for their particular organization -- they've decided to move away from Backbone and don't want developers adding any new Backbone code.
[+] amelius|10 years ago|reply
It makes me feel so sad that the "state of the art" in front-end development is apparently rerunning your render code on every little update. Yes, I know there are shortcuts to making this more efficient, but in essence the technique remains inelegant in the sense that it does not extend well to other parts of the code (that runs computations that might also partially, and not fully, change on an update).
[+] mikekchar|10 years ago|reply
I think you will find that it does extend well to other parts of your code. Code that is idempotent allows you to reason much more effectively about what it will do. It always does the same thing and does not introduce side effects. It also allows you to test it much more easily. In fact, doing computations is one of the places where being idempotent will really clean up your code.

It may seem like a new fangled idea, but actually it has been around for quite a long time. It's just that it didn't really get out of academia and the few shops doing functional programming until lately.

[+] enginous|10 years ago|reply
This pattern of the virtual DOM has some parallels with functional programming. At first look, using functional programming it looks like you're sacrificing the performance that you gain from mutations -- which to some extent is true. But when you look deeper, you'll find that the data structures for functional programming languages have been adapted to work in a very performant way with functional programming patterns.

In the same way, when you look closer at the virtual DOM model, you'll find that you can optimize the usage very well. For example, when you use React with immutable data structures (e.g., Immutable JS), deep equality comparisons can be done very quickly to reduce renders to the minimum subtree required, and to issue the renders for a given change in a batch operation.

With React, you often end up with even faster code than using manual DOM manipulations. Of course, your performance will vary depending on how you implement your code. Depending on which model you're using, and how you program, you may end up with a faster or slower product with either methodology.

But at the end of the day, the performance gain from running code using state mutations just doesn't seem worth the effort of having a significantly harder time reasoning about the code, and having to deal with the challenges of scaling a project where the complexity grows much faster with each line of logic.

And my feeling is that due to the time invested in managing a more complex project that deals with mutations, the "performance per engineering hour" gained for projects using a virtual DOM is more favorable for many projects.

[+] albertoleal|10 years ago|reply
Why is it considered inelegant? If you make your 'render code' stateless, then your issues lie elsewhere other than your render code.
[+] seivan|10 years ago|reply
That's actually what I love about React apart form using hierarchal components as building blocks.

I set the state, and the lib handles the rendering for me. Makes things much easier and is also superior for building UI than e.g UIKit.

[+] matchu|10 years ago|reply
Hand-written code will always beat a framework; React isn't trying to be faster than domain-aware DOM manipulation.

Instead, React seeks to be the state of the art in maintainable view architecture. One of its secondary goals is non-sucky performance, which it does pretty well.

Most devs aren't working on apps where React is the performance bottleneck. If you are, then, well, don't use React.

[+] NoCulturalFit|10 years ago|reply
I would love to read more about styling inline and completely remove external CSS files.

Are there any CSS-frameworks that have been converted to JS but not are not their own components yet? It's easy to find React-Bootstrap but that comes with ready made components, I am looking for styling that's purely in JS so I can make my own components.

Also would a route-component be considered logic or presentation, or maybe it is its own thing and they forgot to mention it?

[+] drhayes9|10 years ago|reply
I don't like inlining styles as objects in React so I went looking for a solution that would work with the toolchain I'm using for my current project.

I'm working on a project now that is using a combination of react-css-modules, webpack, and an ExtractText plugin for webpack that means each React component I write can have an associated CSS file.

Each class in the CSS file gets mangled so that it doesn't affect things globally by react-css-modules. Then the ExtractText plugin for webpack pulls all those CSS files out into one, global styles.css file.

Ultimately, that means that my CSS file might actually, over the life of the project, shrink! Unheard of.

In the same project I'm using redux and redux-router. The router consists of declarative components, like "<ReduxRouter />" and "<Route />".

[+] phleet|10 years ago|reply
We're playing around with inline-styling our components, but pushing the inline-styles into CSS injected into `<style>` tags in the head. It's experimental at the moment, but it's being sent into production shortly: https://github.com/Khan/aphrodite
[+] bryanlarsen|10 years ago|reply
I'm not exactly sure what you're asking for, but I'll try to answer anyways. http://material-ui.com/ is a React component library that uses inline CSS exclusively.