Skip to content

Instantly share code, notes, and snippets.

@kylpo
Last active August 25, 2016 12:36
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kylpo/54c1031633d97758e0de to your computer and use it in GitHub Desktop.
Save kylpo/54c1031633d97758e0de to your computer and use it in GitHub Desktop.
Kylpo's Coding Style

I am a web and mobile developer, using React and React Native. As such, my style has evolved to work more seamlessly with React, and may not work for other frameworks. Also, I LOVE Ruby’s (and CoffeeScript’s) syntax. It taught me the value of code that reads more like english and how aesthetics of a code base truly will affect your and others excitement to maintain/contribute to it.

Code Style

Semicolons

No

// Bad
import Foo from 'foo';
let foo;

// Good
import Foo from 'foo'
let foo

Why

I don’t have any real beef with them, but my code looks better, is more consistent, and faster to write.

  • Looks better is subjective, so I won't go into it. Just look at examples or try it before you decide, please.
  • More consistent because my js looks as my js looks in jsx.
    • For example:
    • <div>{someJavascriptCode()}</div>
    • vs
    • <div>{someJavascriptCode();}</div>
    • Which are you used to seeing in your renders?
  • Faster to code. More than just not hitting the ;, also the time saved from the linter error telling you to add it. You all know you’re guilty of the linter error from time to time.

Quotes

Single

// Bad
const double = "double"

// Good
const single = 'single'

Why?

I used to prefer double because it is the only valid json quote, and it is used in html. Now, with the rise of transpilers, and me using less .json, I prefer the lazy approach of the non-shift-'. It is faster to type, and more importantly, faster to edit. For example, in vim, ci' is honestly way less taxing than ci<shift>'.

Spacing

The following spacing rules are used to satisfy the "reads more like english" request. In general, pad spaces are used around parameters and arguments, and not used around types.

Paren spacing in function args and params?

Yes

// Bad
function myFunc(one, two, three) { ... }

myFunc(a, b, c)

// Good
function myFunc( one, two, three ) { ... }

myFunc( a, b, c )

Except: desctructured params

// Good
function myFunc({ one, two, three }) { ... }

Except: arrow params

// Good
const arrow = (one, two, three) => { ... }

// Good
array.sort( (item, index) => ... )

Why

With arrow params, the added spacing is redundant since it is already padded with spacing outside of the parens.

Paren spacing in statement expressions (like if, switch, logic)?

No

// Bad
if ( x > y ) { ... }

// Good
if (x > y) { ... }

Why

Here, the added spacing in the if expression is redundant since it is already padded with spacing outside of the parens.

Curly spacing in objects

No

// Bad
const obj = { a: 'a', b: 'b' }

// Good
const obj = {a: 'a', b: 'b'}

Why

The lack of spacing clearly denotes that this is a type, and is not destructured.

Curly spacing in destructuring assignments?

Yes

// Bad
import {MyComponent} from 'components'
const {user} = this.props

// Good
import { MyComponent } from 'components'
const { user } = this.props

Why

The spacing here is redundant, but also really useful for skimming code and distinguishing destructuring from objects.

Bracket spacing in array inits

No

// Bad
const obj = [ 1, 2, 3 ]

// Good
const obj = [1, 2, 3]

Why

The lack of spacing clearly denotes that this is a type, and is not destructured.

Bracket spacing in object reference and destructuring

Yes

// Bad
const [a, b] = someArray
const a = someArray[0]

// Good
const [ a, b ] = someArray
const a = someArray[ 0 ]

Why

Destructuring for reasons above. Space in reference for "reading like english", same as function args/params.

if/else

spacing

// Bad
if (isCondition1) {
} else if (isCondition2) {
} else {
}

// Good
if (isCondition1) {
}
else if (isCondition2) {
}
else {
}

Why

All revolves around vertical spacing. The more popular style of housing else on the closing } just clutters up the content of condition1 too much. Also, using the more spaced out version that I prefer has revealed refactoring opportunities for more complex nested if statements. Win win.

Code Conventions

if/else commenting

// Whole if/else comment (likely not needed though)
if (isCondition1) {
  // if condition 1, do...
}
else if (isCondition2) {
  // if condition 2, use...
}
else {
  // otherwise, pass off...
}

Comment on first line of if block IF a comment is necessary. Also using the if _condition_, <verb> format is useful for the reader skimming just the comments.

Function approach

You want to get right to the meat of your function’s purpose. Do not defensively code! This should be done in the function’s parameters.

// Bad
function doSomeCoolLogic( name, names ) {
  if (typeOf name === 'string' && Array.isArray( names )) {
   return names.includes( name )
  }
}

// Good
function doSomeCoolLogic( name = 'default', names = [] ) {
  return names.includes( name )
}

Handler function naming

Passing handlers down as props is common in React.

  • Use handlesEventName if it is the originating handler for an event
  • Use onEventName if it is a function that is calling an onEventName that was passed down to it

Sort function naming

sort functions called by__.

function byNameAscending( a, b ) { ... }

array.sort( byNameAscending() )

React-specific conventions

In general, keep your components as small and focussed as possible (and reasonable). The conventions below will help with this.

Stateless functional components

Gone are the days of renderSection(). Now you should be using a stateless functional component. Note, any exported component should probably still be the class style so that you have access to shouldComponentUpdate and such. Otherwise, consider Recompose.

// Bad
class MyComponent extends React.Component {
 renderItem() {
  return <div/>
 }
 
 render() {
  return (
   <div>
    {this.renderItem()}
   </div>
  )
 }
}

// Good
const Item = props => <div/>

class MyComponent extends React.Component {
 render() {
  return (
   <div>
    <Item />
   </div>
  )
 }
}

Extract non-this functions out of component

Utility functions that do not actually use any instance properties should not exist within the component definition. They should be above the component definition, or in some separate, imported helpers file.

// Bad
class MyComponent extends React.Component {
 getNamesFromItems( items = [] ) {
  return items.find( item => item.name )
 }
 
 render() {
  const names = this.getNamesFromItems( this.props.items )
  
  return ( ... )
 }
}

// Good
function getNamesFromItems( items = [] ) {
  return items.find( item => item.name )
}

class MyComponent extends React.Component {
 render() {
  const names = getNamesFromItems( this.props.items )
  
  return ( ... )
 }
}

inline styles

Inline styles place at the bottom of the file for RN (and web React if using something like Radium).

_privateMethod vs publicMethod

Since ~99% of components will use props, and not be accessed via public methods, prefer the publicMethod format for all functions, and clearly comment when one is truly public (in that a component will use this.refs.myComponent.publicMethod()).

// Bad
class MyComponent extends React.Component {
 ...
 
 _resetScrollValue() {
  this.setState({ scrollValue: 0 })
 }
 
 scrollTo( scrollValue = 0 ) {
  this.setState({ scrollValue })
 }
 ...
}

// Good
class MyComponent extends React.Component {
 ...

 resetScrollValue() {
  this.setState({ scrollValue: 0 })
 }
 
 /* PUBLIC */
 scrollTo( scrollValue = 0 ) {
  this.setState({ scrollValue })
 }
 ...
}

Some good resources

9 things every React.js beginner should know - Cam Jackson

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment