A cheatsheet for javascript syntax with added Swift examples where relevant. Most of this is generic javascript stuff but there's some react specific info at the bottom.
// 'const' for a variable that will not change, eslint will warn you if you try to mutate this
// 'let' for a mutable variable, you may also see var in some tutorials which is sort of the legacy version of let
// Always prefer const, only use let when absolutely necessary. This makes it clear which variables are likely to be reassigned over time!
const x = 0
let y = 0
x = x + 1 // error
y = y + 1
Arrays, objects and functions are reference types (i.e. you will be editing the same instance of the thing in memory when creating a second reference to it), everything else (bool, int, string etc) is a value type. Read more here.
const myObject = {
a: 1,
b: ""
}
// Shorthand, if you are setting an object where the variable name of the value is equal to the key, then you can omit the colon-key.
const b = ""
const myObject = {
a: 1,
b
}
class MyObject {
let a: Int
let b: String
}
let myObject = MyObject(a: 1, b: "")
Something that is used all the time in javascript which seems pretty alien if you are used to a language like Swift.
const myObject = {
a: 1,
b: ""
}
// Two ways to get 'a' and 'b'
// Method 1
const a = myObject.a
const b = myObject.b
console.log(a) // yields 1
console.log(b) // yeilds blank string
// Method 2
const { a, b } = myObject
console.log(a) // yields 1
console.log(b) // yeilds blank string
class MyObject {
let a: Int
let b: String
}
let myObject = MyObject(a: 1, b: "")
let a = myObject.a
let b = myObject.b
print(a) // yields 1
print(b) // yeilds blank string
The rest operator gets the 'rest' of the values from an object.
const myObject = {
a: 1,
b: "",
c: "something"
}
const { a, ...otherProperties } = myObject
console.log(a) // yields 1
console.log(otherProperties) // yields an object equal to myObject omitting a, { b: "", c: "something" }
const myObject = {
a: 1,
b: "",
c: "something"
}
const anotherObject = {
d: 5,
...myObject
}
console.log(anotherObject) // yields an object that is the merge of myObject into anotherObject e.g. { a: 1, b: "", c: "something", d: 5 }
The same spread operator works with arrays.
const myArray = ["a", "b", "c"]
const [thing1, thing2] = myArray
console.log(thing1) // yields a
console.log(thing2) // yields b
It can also be used to join to arrays
const myArray = ["a", "b", "c"]
const otherArray = ["d", "e"]
const joinedArray = [...myArray, ...otherArray]
console.log(joinedArray) // yields ["a", "b", "c", "d", "e"]
And can be used to get the first item separetely to the rest of the array.
const myArray = ["a", "b", "c"]
const [firstItem, ...otherItems] = myArray
console.log(firstItem) // yields "a"
console.log(otherItems) // yields "b", "c"
// Must use backticks
const x = `My string with my variable equals ${myVariable}`
let x = "My string with my variable equals \(myVariable)"
console.log("My thing", objectIWantToDebug")
console.warn("My thing", objectIWantToDebug") // useful in react native as shows in yellow banner on screen without having to attach external debugger
// Useful sidenote that console.warn() or console.log() return undefined which is falsy so you insert logs without having to break code out into pieces.
const myFunction = (x, y) => console.log("getting max of ", x, y") || Math.max(x,y)
print("My thing", objectIWantToDebug")
If you type debugger
into the developer tools console, JavaScript will pause at that point in execution, you'll be able to see the call stack and current variables, and you'll be able to manually step through code. Much more powerful and flexible than just using console.log
.
You can also set breakpoints in code. These are not as powerful as those in Android Studio or Xcode but can pretty useful for viewing a call stack etc. To do this click on the sources tab in chrome developer tools or react-native-debugger. For react-native first ensure that you have enabled Debug JS Remotely
through Command + D
on iOS and Command + M
on Android. Then go into react-native-debugger -> sources -> dropdown RNDebuggerWorker.js -> dropdown your IP -> intl-web-app then navigate to where you want to breakpoint. Add it by clicking in the gutter on the left where the line numbers are. Annoyingly if you reload JS whilst navigating then your position will be lost, however breakpoints - once set - are retained across reloads.
const myFunc = () => {}
// or
function myFunc() {
}
let myFunc: () -> Void = {
}
// or
func myFunc() {
}
const myFunc = () => 1
// or
function myFunc() {
return 1
}
let myFunc: () -> Int = {
return 1
}
const myFunc = () => ({})
let myFunc: () -> MyObject = {
return MyObject()
}
const myFunc = () => () => {}
let myFunc: () -> (() -> Void) = {
return {
}
}
Using code from other files in javascript must be imported/required. Importing is done when 'compiling' javascript, whereas requiring is done inline at runtime. Anything you want to make public to other files you must 'export'.
/// fileA.js
export const myVariableInFileA = "something"
///
/// fileB.js
import { myVariableInFileA } from './fileA'
// or
const myVariableInFileA = require('./fileA').myVariableInFileA
///
One key thing to note (I didn't know this and spent far too long trying to work out what was wrong) is that there are default and named exports. The default export does not need to be destructed if using the import
syntax - which also means each file can only have one default export.
///////////// fileA.js
const myVariableInFileA = "something"
export default myVariableInFileA
export const otherVariableThatIsNotDefault = "other thing"
/////////////
///////////// fileB.js
import myVariableInFileA from './fileA' // notice the no brackets for destructuring as this is the default export
import { otherVariableThatIsNotDefault } from './fileA'
// or
const myVariableInFileA = require('./fileA').default
const otherVariableThatIsNotDefault = require('./fileA').otherVariableThatIsNotDefault
/////////////
React Components can be defined as either functions or as classes. The return of the function is the same as the return of the render
function of the class. If using a class, props are a property on that class, if using a function then the props are an argument to that function.
Functions are generally the preferred way to write components, however they do come with one drawback in that they do not have 'state' like class components do. This means you cannot run setState
in order to trigger a re-render. You also do not get access to react lifecycle events like componentDidMount
. A new and upcoming proposal to React called hooks is likely to add this functionality in the near future. But currently, if you need state or lifecycle then you have to use a class (or a hoc that provides desired functionality). If you don't need those, you can use a function component. Generally using functions will give you more concise, potentially more performant (as react doesn't need to assign state to your component) and easier to test code.
import React, { PureComponent } from 'react'
import { Text } from 'react-native'
class MyView extends PureComponent {
render() {
const { textToDisplay } = this.props
return <Text>
{textToDisplay}
</Text>
}
}
// is the same as
const MyView = ({ textToDisplay }) => {
return <Text>
{textToDisplay}
</Text>
}