React.js Cheat Sheet

Who needs Vanilla-js?

#Components

Why components?

React.js components allow you to split the whole app into individual components and reuse them. The idea follows the don't-repeat-yourself philosophy.

Functional Component

const Person = () => {
    return <p>Max</p>
} 
// or:
function Person() {
    return <p>Max</p>
}
<Person/>  // renders <p>Max</p>

Component with Props

function Person(props) {
    return <p>{props.name}</p>
}
<Person name='Anna'/> // renders <p>Anna</p>
Props work like parameters in functions. We can pass them into a component, generating an individual output.

Multiple Props

function Person(props) {
    return <p>{props.name}, {props.age}</p>
}
<Person name='Anna' age={23} /> 
// renders <p>Anna, 23</p>
Thanks to the Spread Operator, we can decompose the object.

#Shorthands

ES6 Shorthands in React.js

Many Shorthands of JavaScript can be used in React.js - they make your code cleaner, easier readable and slimmer.
I wrote an article on this topic: 4 Useful JavaScript-Shorthands for React.js

if-else-shorthand in JSX

const OurComponent = () => {
    return (
        <div>
        {6 > 5 ? (
            <p>6 is greater</p>
        ) : (
            <p>6 is less or equal</p>
        )}
        </div>
    )
}

Another example

function App() {
    return (
        <div>
        {!loading ? (
            <p>Main content</p>
        ) : (
            <p>loading...</p>
        )}
        </div>
    )
}
A more useful example

Spread Operator in JSX

const PersonComponent = (props) => {
    return (
        <p>
            {props.name} is {props.age} years old
        </p>
    )
}
function App() {
    const props = { name: 'Max', age: 23 }
    return <PersonComponent {...props} />
}
Thanks to the Spread Operator, we can decompose the object.

Destructuring in React.js

const [count, changeCount] = useState(0)
count 
// returns the current state '0'

changeCount(5) 
// function, to change the state to '5'
We usually use destructuring when setting up our state with hooks. Learn more about destructuring here

Destructuring with props

const Person = (props) => {
    return (
        <div>
            <p>Name: {props.name}</p>
            <p>Age: {props.age}</p>
        </div>
    )
}
const Person = (props) => {
    const { name, age } = props
    return (
        <div>
            <p>Name: {name}</p>
            <p>Age: {age}</p>
        </div>
    )
}
Same result, but the second example looks much better, right?

#Event Handling in React

Onclick events

function hello() {
    alert("hello")
}

function App() {
    return <button onClick={hello}>
        Click me
    </button>
}
Providing the function, which should me executed as a variable, will work. Important: Do not call the function with the bracktes-syntax. This will executed the function instantly.

Onclick events - anonymous function

function App() {
    return <button onClick={() => alert('hello')}>
        Click me
    </button>
}
Same result as in the example before, but without declaring a function.

Handling Forms

function App() {
  const [input, changeInput] = useState("")

  function handleChange(event) {
    changeInput(event.target.value)
  }

  return (
    <form onSubmit={() => alert(input)}>
      <input type="text" value={input} onChange={handleChange}/>
      <input type="submit" value="Submit"/>
    </form>
  )
}
This example uses hooks to save the input in the form. With the onSubmit attribute we can handle submitting forms on our own.

#Hooks in React.js

What are Hooks in React?

Hooks are the new way to deal with state, and lifecycles of components. Replacing the state-object, componentDidMount, componentDidUpdate and many more things - while making class-based code completely unnecessary.

useState Hook

function App() {
      const [count, setCount] = useState(0)
      return (
          <div>
            <p>The count: {count}</p>
            <button onClick={() => setCount(count + 1)}>
              Increment
            </button>
          </div>
      )
  }
Through destructuring, we receive two variables from the useState hook: The first one is the actually state, count, the second one, the function to alter the state setCount

useEffect - componentDid Mount & Update

function App() {

    useEffect(() => {
      console.log("component just rendered")
    }, [])

    return (
        <div>
          <p>Hello World!</p>
        </div>
    )
}
When passing in an empty array as second argument for useEffect, the Hooks behaves like componentDidMount and componentDidUpdate. When executing the code, the Hook will be only executed once.

useEffect - detecting state changes

function App() {
  const [count, setCount] = useState(0)

  useEffect(() => {
    console.log("count changed")
  }, [count])

  return (
      <div>
        <p>The count: {count}</p>
        <button onClick={() => setCount(count + 1)}>
          Increment
        </button>
      </div>
  )
}
When passing an actually state in the array of useEffect, the Hook will be only executed once.

useEffect - componentWillUnmount

function Status() {
  useEffect(() => {
    console.log("mounted")
    return () => {
      console.log("unmounted)
    }
  })

  return <p>I am here! </p>
}

function App() {
  const [visible, setVisible] = useState(false)

  return (
      <div>
        <p>Optional component:</p>
        {visible && <Status />}
        <button onClick={() => setVisible(!visible)}>
          Toggle visibility of Status
        </button>
      </div>
  )
}
What is happening inside the return expression is the code, which is run on the cleanup as it is often called. Both the logs fit what is happening: Mounting / rendering and unmounting, when visible is set to false.

useRef - referencing native DOM elements

function App() {
	const elementRef = useRef()

	useEffect(() => {
		const divElement = elementRef.current
		console.log(divElement) 
    // logs <div>A random div</div>
	}, [])

	return (
		<div ref={elementRef} id="something">
			A random div
		</div>
	)
}
useRef can be used to reference elements in the DOM - the example prints the rendered div as an HTML objects, just like in plain JS. The example is based on dmitripavlutin.com's awesome tutorial.

useMemo - memoizing values

function App() {
	const [count, setCount] = useState(10)

	const expensiveComputation = useMemo(() => {
		return count * 2
	}, [count])

	return (
		<>
			<p>Count: {count}</p>
			<p>Expensive count: {expensiveComputation}</p>
			<button onClick={() => setCount(count + 1)}>Increment count</button>
		</>
	)
}
useMemo memoizes a value, based on a state. It helps to avoid repeating expensive computations on every render, when the original state isn't even changed. Therefore, the memoized value will only be recomputed, when the state is changed.

useReducer - Redux-like state handling

function App() {

	function reducer(state, action) {
		switch (action.type) {
			case 'plus':
				return state + 1
			case 'minus':
				return state - 1
		}
	}

	const [count, dispatch] = useReducer(reducer, 0)

	return (
		<>
			Count: {count}
			<button onClick={() => dispatch({ type: 'plus' })}>Plus 1</button>
			<button onClick={() => dispatch({ type: 'minus' })}>Minus 1</button>
		</>
	)
}
useReducer is a more complex alternative to useState. While altering the state with useState works directly, useReducer first dispatches and action, and offers to check how to compute the state first.

useCallback - memoizing component functions

function App() {
	const [count, setCount] = useState(10)

	const doubleCount = useCallback(() => {
		return count * 2
	}, [count])

	return <ChildComponent getValue={doubleCount} />
}
When writing a function inside a component, a new function object is created on each render. Especially, when a function is passed down to multiple child components, this often means unnecessary computations. useCallback memoizes a function, to solve this problem. The function object is only recreated, when the referred state changes.