Joshua's Cheatsheets - React / JSX - Cheatsheet
Light
help

Other resources

My other pages:

External resources:

What & Link Type
"The React Handbook" by Flavio Copes - Online version PDF signup
   ---> Amazing resource!
Guide
"React for Vue Developers" by Sebastian De Deyne Guide / Cheatsheet
React Lifecycles Method Diagram Cheatsheet
React+TypeScript Cheatsheets Cheatsheet
PluralSight: Composing React Components with TypeScript Guide
Post: "You Probably Don't Need Derived State" Guide
Collection: enaqx/awesome-react Collection
Kent C. Dodds - "Super Simple Start to React" Guide

Binding template literal

Binding template literal to property expecting string: You have to use double brackets to "break out" of JSX and into regular JS. Instead of:

<SEO title="`${props.pageContext.slug}`" />

You need:

<SEO title={`${props.pageContext.slug}`} />

Creating unique keys

You want a unique identifier, which is actually harder than one might expect to create. Using the index provided within a loop is not recommended, and even combining with something like (new Date()).getTime() is not guaranteed to be unique.

There are tons of packages out there that you can drop in to create unique Ids. Or just make a composite key out of enough unique parameters to ensure non-duplicates.

Misc / How Do I...

  • You can now use empty elements, known as fragments, to wrap siblings:

    • <><div></div><div></div></>
  • Issues returning JSX?

    • More than one line? Make sure wrapped in parenthesis return (<div></div>)
    • Make sure there is *only one* root level element
  • Pass a bunch of options to a component as props (basically convert JS Obj to props)

    • Just use spread operator - {...props}
    • You can use this re-use the same props across multiple components!
    • Be careful about directly spreading vs capturing via rest parameters and then spreading - you might not want to pass all props to child component

      • This is why you often see const {myVarA, myVarB, ...restProps} = props; inside components -> restProps would be a subset of props that does not contain myVarA or myVarB
  • Simulate a change event on a <input> element

  • How to add an external stylesheet (not for bundling)

    • Instead of using import within a JS file (like App.js), add the stylesheet directly as a link tag element in the HTML file (e.g. <link rel="stylesheet" href="https://.../style.css" />)
  • How do I access an element directly (similar to native browser APIs like document.getElementById) in React? How do I get the DOM node?

    • That is a great use case for React refs! - Docs
    • Options:

      • Newest and recommended: useRef hook

        • myRef = useRef(null)
      • Older:- this.myRef = React.createRef() in class constructor
    • You can access DOM node through myRef.current, after attaching via <MyElement ref={myRef}/>
  • How do I expose and call a function from a child component in a parent component (aka passing methods up through the component tree)?

    • This is considered a bit of an anti-pattern with React, and is generally avoided entirely (things are always passed down, not up).
    • However, there are still ways to do so - the main way is to use refs (S/O, Docs)
  • What's with the {} curly braces? Is this Mustache or Handlebars templating?

    • No, the curly braces simply tell the JSX compiler that you are about to give it something that should be evaluated as a JavaScript Expression, rather than a string or component.

Tips

  • You can assign JSX to variables! Makes it very easy to reuse!
  • Make use of object destructuring assignments to avoid repetitive props syntax

    • const {hidden, dataArr, isAdmin, isAuthed} = this.props
    • -> Or, destructure right in function argument, const myComponent = ({hidden, dataArr, isAdmin, isAuthed}) => {}
  • You can use class members and/or regular vars to hold changing values, as opposed to putting in state/props, if you want to avoid unnecessary renders when those values are not part of UI

Asset management and usage

You have two main options when it comes to asset management:

  • Public Folder: Place in /public

    • Pull into HTML with %PUBLIC_URL%
    • Pull into JS with process.env.PUBLIC_URL
  • Bundling: Place asset files alongside JS, in /src

    • Pull into JS by using import at top of file with relatively path
    • Pull into css (e.g. for background image) with relative path

The second option is always preferred, since it uses webpack to bundle assets and will help keep the size of your app down by only bundling assets that are actually used (as well as some other tricks).

Importing assets in JS or CSS

Examples:

JS:

import background from './assets/background.jpg';
// ...
render() {
	return (
		<img src={background} />
	)
}

CSS:

#main {
	background-image: url(./assets/background.jpg);
}

Getting around method binding of this

A common issue with React is preserving the value of this, especially when it comes to event handlers, like onClick.

If the callback you are assigning uses this within its body, you will have issues if the value of this changes (most often in a Cannot read property '___' of undefined error).

Here are some ways to ensure the value of this stays the way you want it to:

Explicit, with .bind() on the attribute

The older method was commonly to use .bind() to explicitly bind the value of this at the point of attaching the handler. That might look something like this:

<CustomComponent onClick={this.handleEvent.bind(this)}>

ES6 Class binding

If you are using the new ES6 class syntax, you have all the other options, plus a few more. Let's say this is our base code:

class MyComponent extends React.Component {
	constructor(props) {
		super(props);
		this.state = {counter: 0};
	}

	handleClick(evt) {
		const updatedCount = this.state.counter + 1;
		this.setState({
			counter: updatedCount
		});
		console.log(this.state.counter);
	}

	render() {
		return (
			<button onClick={this.handleClick}> Counter + </button>
		);
	}
}

One option is to use .bind(), in the constructor:

constructor(props) {
	super(props);
	this.state = {counter: 0};
	// ADDED:
	this.handleClick = this.handleClick.bind(this);
}

Another option is to turn the handleClick method, into a member, that is the value of an arrow function, thus automatically binding this to the class:

// Rest of class definition
// Or: public handleClick = (evt) => {}
handleClick = (evt) => {
	const updatedCount = this.state.counter + 1;
	this.setState({
		counter: updatedCount
	});
	console.log(this.state.counter);
}
// ...

Technically, this is actually an ES6 public field, which is, as of 2019, in an experimental stage, so while it is well supported with transpiled JS/TS, it has limited native browser support.

Inline arrow functions

One of the benefits (or drawbacks) of arrow functions is that they lexically bind this - automatically. So, if you do:

<CustomComponent onClick={(evt) => {
	this.handleEvent(evt);
}}>

It doesn't matter if CustomComponent has a different this scope, because the arrow function binds the callback where you defined it!

Use createReactClass

If you use createReactClass, you generally don't have to worry about this issue, as createReactClass uses autobinding, which basically does .bind() for you.

More reading


Computed properties

Unlike Vue, which has a specific syntax for computed properties, React doesn't really care how you try to formulate values based on computed state properties.

ES6 Class - Getter

With the new ES6 class based approach, a very clean solution is to use getters, with something like:

class MyComponent extends React.Component {
	// ... class stuff
	get isAdult() {
		return typeof(this.state.age) === 'number' && this.state.age > 18;
	}
}

Within the render function itself

There is nothing preventing you from computing a value within the render function itself. For example:

class MyComponent extends React.Component {
	// ... class stuff
	render() {
		const isAdult = typeof(this.state.age) === 'number' && this.state.age > 18;
		return (
			<div>
				Is adult = {isAdult.toString()}
			</div>
		);
	}
}

As a function

Another vanilla solution here is to simply use a function to return the computed value, rather than anything else. How you declare this is up to you:

  • Explicitly, with function myFunction(){}
  • As a ES6 class member

    • public isAdult() {}
  • With an arrow function to bind this

    • const isAdult = () => {};
  • Etc.

To use within your render method, simply make sure you actually execute it by following it with the parenthesis and arguments if applicable.

State management system

If you are using a dedicated state management system, there is a chance that what you are using might already have something in place to not only provide explicit computed properties, but also optimize them, to prevent redundant expensive re-calculations.

For example, if you use MobX, make sure to check out this page on computed values.

Further reading:


Handlebars / Mustache type logic (loops, conditional, etc)

Conditional rendering

Tons of options - see "7 ways to implement conditional rendering".

Some tricky ones to remember, but can be very helpful are:

  • AND (&&) operator to show or hide

    • You can use {shouldShowBool && <div>I'll only show up if shouldShowBool is true!</div>}
    • This works because in JS, A && B returns B if A is true, without coercing B to a boolean
  • Ternary Operator (_?_:_) to swap between things

    • You can use {isLeaving ? <p>Goodbye!</p> : <p>Hello!</p>}

Loop / array render

The main way to render an array of something in React is to simply pass an array of JSX, within a JavaScript Expression block (e.g. {myJsxArr}). However, there are many ways to write this code:

You could:

  • Create an array of JSX template code assigned to a variable, and use it within render(), with something like: items.push(<div key={UNIQUE_KEY}>{CONTENT}</div>);
  • Iterate over the items directly in render(), and return the template there:

    const render = function() {
    	const items = ['bread', 'milk', 'cookies'];
    	return (
    		<ul>
    			{items.map((value, index) => {
    				return <li key={index}>{value}</li>
    			})}
    		</ul>
    	);
    }
  • Use an IIFE to construct and return the array, all inline within the JSX:

    <div>
    	<h1>One through Ten:</h1>
    	{(function () {
    		const jsxArr = [];
    		for (let x = 1; x <= 10; x++) {
    			jsxArr.push(<p key={x}>Number {x}</p>);
    		}
    		return jsxArr;
    	})()}
    </div>
    • This is kind of an anti-pattern, so I would avoid and instead construct the array further up in the component before starting to return JSX / HTML.

React Hooks

See my separate cheat sheet.

React - TypeScript and TSX

👉I also have a general cheat sheet on TypeScript you might find helpful!

React - TypeScript and TSX - Resources

React - Common TS Issues

  • Error using component: '__' cannot be used as a JSX component. Its return type '___' is not a valid JSX element. + ts(2786)

    • Read the full error message to be sure, but this could be because you indeed have something unsafe or incorrectly typed
    • In some cases, this can be caused by type definition files getting "out of sync". Especially if the specific error is that the return type might be null, but you know it shouldn't be

      • Try completely deleting node_modules, all lock files, and then re-installing
    • Does adding @types/react as a devDependency fix it?
    • Are you using Preact? You might want to take a look at scurker/preact-and-typescript guide, or see if this specific issue (around preact/compat) applies.
  • Cannot find name '___'

    • Did you accidentally name your file with .ts instead of .tsx?
    • Make sure you have configured the jsx and jsxFactory in compilerOptions in the TSConfig

React - Common TS Syntax Stuff

  • Declaring prop types
// All of the below are acceptable

// We can define the shape of props separately
interface BirthdayProps {
	age: number;
	name: string;
}
export const BirthdayGreeting = (props: BirthdayProps) => (
	<span>{`Congrats ${props.name} on turning ${props.age}`}</span>
);


// ...or, we can inline it
export const BirthdayGreeting = (props: { age: number; name: string }) => (
	<span>{`Congrats ${props.name} on turning ${props.age}`}</span>
);

// And we can also use destructuring for easier nested prop access:
export const BirthdayGreeting = ({ age, name }: { age: number; name: string }) => (
	<span>{`Congrats ${name} on turning ${age}`}</span>
);
  • Reusing Prop Types / Extracting Prop Types

    • You can use ComponentProps<typeof MyComponent> (or ComponentPropsWithoutRef)

      • For standard elements, you can use with string constant ComponentProps<'div'>
    • Optimally, if using a library that separately exports Prop types, import & use that directly (e.g. import {BoxProps} from '@chakra-ui/core')
    • See this S/O answer
  • Taking generic props / extending another component props

    • It kind of depends on how specific you want to be, and what exact ecosystem you are using (react, preact, etc.)
    • It is usually best to combine your custom props with either:

      • A props interface exported from your framework (e.g. BoxProps from Chakra UI)

        • Or...
      • React.ComponentProps<T> utility

        • See reusing prop types section above for details
    • Example: Custom component that allows parent to pass all standard <div> props 👇

      interface Props {
      	name: string;
      }
      
      const MyComponent = (props: Props & ComponentProps<'div'>) => {
      	return (
      		<div {...props} className={['myComponent', props.className].join(' ')}>
      			<span>Hello {props.name}</span>
      		</div>
      	)
      };
  • Accepting components through props / passing children

    • The type signature of children is kind of tricky in React. In general, practically anything can be a child, so the type is pretty wide.
    • In standard React:

      • the type for props that accept children looks like this: P & { children?: ReactNode }; (src)
      • And ReactNode can practically be anything:

        • type ReactNode = ReactChild | ReactFragment | ReactPortal | boolean | null | undefined; (src)
        • This gets expanded even further...
    • In preact:

      • Type for props with children looks like: P & { children: ComponentChildren } (src)
      • Just like in React, this gets expanded until it represents practically anything (src)

Material-UI Notes

Material-UI: Media Queries

In general, the docs on breakpoints are a good place to start. Here are a few options:

  • You can use them directly in makeStyles:

    const useStyles = makeStyles(theme => ({
    	myStyle: {
    		width: '100px',
    		'@media (min-width: 1000px)': {
    			width: '400px',
    		},
    		// Or, with theme settings
    		// https://material-ui.com/customization/breakpoints/#css-media-queries
    		[theme.breakpoints.up('sm')]: {
    			width: '200px',
    		},
    	}
    }));
  • You can use the provided useMediaQuery hooks
Markdown Source Last Updated:
Wed Oct 21 2020 06:31:00 GMT+0000 (Coordinated Universal Time)
Markdown Source Created:
Wed Aug 21 2019 20:31:01 GMT+0000 (Coordinated Universal Time)
© 2020 Joshua Tzucker, Built with Gatsby