coryhouse / coryhouse/reactjsconsulting

Advanced React

Open
#1 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
JavaScript
Stars
374
Forks
33
PR merge metrics
No merged PRs in 30d

Description

Note: [I deliberately leave many of the topics below out of fundamentals](https://twitter.com/housecor/status/1141354438571057152).

React top level api: https://reactjs.org/docs/react-api.html

## Upcoming "use" hook

Primitive for handling asynchrony.
Works like “await” inside non-async client-side components.
Wrap promises (and soon other things like context) with “use”.
If a promise passed to use isn’t resolved, “use” suspends the component’s execution by throwing an exception. The component replays when the promise resolves.
A “usable” type is a wrapper for a value. Calling “use” unwraps it.
Only for client (like most hooks).
Async server components use plain async/await.
Only non-async server components can use hooks.
Unlike other hooks, can be called conditionally. Why? Because the data lives in the promise object itself. So there’s no need to store state for “use” across updates.
Can be placed in the same spots as “await” including blocks, switch statements, and loops.
Part of the “Data fetching with Suspense” story.

## [UI Architect](https://twitter.com/housecor/status/1189719108562096130) / Frontend Architect / FrontendOps /

ops - Responsibilities:

State management / Finite State Machines / Statecharts
Reusable components, scripts, styles
Design system / Style Guide (collaboration)
Dev environment (transpiling/bundling/linting...) and dev tools
Build automation
Mock APIs
Automated testing (unit/integration/visual)
App composition/slicing
Error handling
Event Modeling
Accessibility
Performance
Security
Dev tools
Dependency management
[More here](https://github.com/stevekinney/frontend-architecture-topics) and [here](https://giamir.com/frontendops)

## Signs it's time to consider extracting a new component

- Duplicated JSX (extract to the same file if not reused elsewhere) - [see #8 here](https://dev.to/jsmanifest/14-beneficial-tips-to-write-cleaner-code-in-react-apps-1gcf)
- Reuse
- JSX gets difficult to read
- To allow thinking about page sections in isolation (each component becomes a black box, which reduces cognitive load)
- Props list gets long
- Document different states in Storybook, create dedicated image tests with Chromatic/Percy/etc
- API calls and JSX in same component - Extracting API concerns means you can feed mock data via props
- Performance (extract an expensive portion so you can optimize its rendering)
- To keep style selectors short (whether it be BEM or CSS Modules, smaller components = smaller namespace = can use nice short names and easily navigate). [If you find yourself prefixing selectors by section like this](https://www.dropbox.com/s/07veoyq5dkxr8ip/Screenshot%202019-08-11%2019.52.59.png?dl=0), consider extracting a component.
- To divide work between people/teams

## Why prefer fewer components?

- Less jumping between files
- Minimize prop drilling and propType declaration overhead
- Shallow trees may be easier to understand than a deeply nested tree
- Every new file adds a little bloat to the bundle due to Webpack's bundling overhead

So it's a tradeoff.

Useful middle ground here: You can declare multiple components in a single file, but export only the "parent". This avoids jumping between files and provides a clear public API. If you prefer separate files, you can create a component folder and place all its child components in that folder, then use a barrel to export only the Header.

- Summary: [When I place React components in separate files](https://twitter.com/housecor/status/1220671289926594561)

## Brain Teaser

[Why doesn't the onSubmit fire here](https://codesandbox.io/s/nervous-sammet-il5is)?

## Patterns for scaling
- [ ] Decompose React components by [separating view from logic, and extracting most the code out of them into custom hooks, and classes](https://martinfowler.com/articles/modularizing-react-apps.html) - Great post on martinfowler.com. Ask: How much code could I reuse if I switched from React to x?
- [ ] Declare [global event handlers](https://reactjs.org/docs/events.html#supported-events) in the capture phase by appending `Capture` to event name. `onClickCapture`, `onHoverCapture`, etc. [Example](https://twitter.com/housecor/status/1254790913139892224)
Useful for large apps, multiple apps in the org, or cross-cutting concerns
- [ ] "Vertical" slicing: Split app by top-level nav
- [ ] "Tiny" slices / mixed tech: Micro frontends
- [ ] [Overview on Martin Fowler](https://www.martinfowler.com/articles/micro-frontends.html)
- [ ] [MFE with React and Vue](https://dev.to/dabit3/building-micro-frontends-with-react-vue-and-single-spa-52op)
- [ ] Use context in subtrees (see below for context)
- [ ] Share component across separate teams
- [ ] Create a [company framework](https://github.com/coryhouse/rjc/issues/9)
- [ ] Review [large open source projects](https://github.com/coryhouse/rjc/issues/13) <- See "Code worth reading" and identify patterns used for scaling
- [ ] [Centralize URL declarations](https://twitter.com/housecor/status/1229817559396081664)

## Advanced Hooks

- [ ] [useReducer](https://reactjs.org/docs/hooks-reference.html#usereducer) - Alternative to useState. Easily test in isolation. Move state logic from component to separate file. Useful to avoid having many useState declarations and multiple calls to setState in a row. Also preferable when next state depends on the previous state (though callback form of useState also helps there). Also a valid alternative to useCallback because you can pass dispatch down instead of callback funcs. Dispatch identity is stable - it doesn't change over renders.
- [ ] [useCallback](https://reactjs.org/docs/hooks-reference.html#usecallback) - Memoize a func so that children get the same reference with each render. Useful when children are expensive to render and thus need to avoid needless re-renders due to function props changing. In other words, child components that use `React.memo`, `shouldComponentUpdate`, or `PureComponent` to avoid re-renders benefit from having a parent that uses useCallback to avoid needlessly sending down a new func reference on each render.
- [ ] Tip: Struggling with useCallback dependencies causing it to be reallocated? Pass arguments to the function instead so that it has no dependencies.
- [ ] [useMemo](https://reactjs.org/docs/hooks-reference.html#usememo) - Memoize an expensive value to avoid re-calculation on every render.
- [ ] [useRef](https://reactjs.org/docs/hooks-reference.html#useref) - Create a reference to a DOM element or hold a value that isn't rendered
- [ ] [useImperativeHandle](https://reactjs.org/docs/hooks-reference.html#useimperativehandle) - Combine with useRef. Use to customize the value provided by ref. Allows parent to call arbitrary functions in child. For example, focus child's component's input. [demo](https://codesandbox.io/s/charming-rain-wen5h)
- [ ] [useLayoutEffect](https://reactjs.org/docs/hooks-reference.html#uselayouteffect) - useEffect runs after render. This runs **before** render. Useful when you want to calculate position before rendering.
- [ ] [useDebugValue](https://reactjs.org/docs/hooks-reference.html#usedebugvalue) - Apply to custom hooks you share in a library so they have a useful label in devTools.

## Example Custom Hooks

- [ ] https://usehooks-ts.com
- [ ] https://usehooks.com/
- [ ] [Validate search params via Zod](https://twitter.com/housecor/status/1734610338010616100)
- [ ] [Rehooks is a huge repo of custom hooks](https://github.com/rehooks) and [beautiful-react-hooks](https://github.com/beautifulinteractions/beautiful-react-hooks)
- [ ] [useHasCamera](https://gist.github.com/coryhouse/42cca17800a3ab6db3cdf99509ee3536)
- [ ] [useSafeState](https://gist.github.com/coryhouse/9b7b5265b6e9038558adf71e70d96841) - There's a [good thread here that discusses the merits of this approach](https://www.reddit.com/r/reactjs/comments/e88mu2/why_is_there_no_usesafestate_hook_in_react/). Ideally, we'd cancel the async call which would be a more direct approach. [Axios supports cancellation](https://github.com/axios/axios#cancellation), so that's arguably a better option. But I will admit that cancellation is a hassle compared to this, and likely not worth the extra effort.
- [ ] [useIsMounted](https://twitter.com/jasonlunsford/status/1263842312733577226/photo/1) - Check if mounted. Useful to determine whether a component has mounted for use in other custom hooks. Also useful in async processes within components. Pretty handy in try/catch/finally blocks for example.
- [ ] [useAutoSave](https://codesandbox.io/s/useautosavefinal-xhsyx?file=/src/useAutoSave-4.js) - auto save when data changes
- [ ] [useAlert](https://gist.github.com/coryhouse/254595cf20a3b1ffbedce44aa7259f42)
- [ ] [usePrevious](https://reactjs.org/docs/hooks-faq.html#how-to-get-the-previous-props-or-state)
- [ ] [useIsMobile](https://codesandbox.io/s/cool-star-rzkko)
- [ ] [useMouseCoordinates](https://codesandbox.io/s/autumn-fast-7dzd1) - Mouse coordinate tracker
- [ ] [useApiCall](https://github.com/ryanlanciaux/coffee-shop-example/blob/master/src/screens/index.js#L37) - Wrap API calls in a hook to encapsulate the redundancy of tracking response, loading, and error state. Enhancement: mimic the "Only one loader" behavior by incrementing a counter each time a call starts and decrementing a counter each time a call completes or errors. Share `numApiCallsInProgress` or an array of `apiCallsInProgress` with an identifier for each between hooks via context.
- [ ] [useLocalStorage](https://usehooks.com/useLocalStorage/) - Every call to setState persists to localStorage
- [ ] [useAsync](https://codesandbox.io/s/handling-async-actions-via-custom-useasync-hook-sfyot) - for handling an async call with loading states and errors. [blog post](https://levelup.gitconnected.com/performing-async-actions-using-hooks-e4da47293d8e)
- [ ] [useForm](https://github.com/upmostly/custom-react-hooks-form-validation/blob/master/src/useForm.js) - simple hook for handling form state and errors
- [ ] [useRequiredFields](https://tvernon.tech/blog/react-custom-hook-for-forms) - Form with **uncontrolled** inputs, but values are required - [Codesandbox](https://codesandbox.io/s/agitated-goldberg-rbkzm)
- [ ] [Note: Avoid declaring dep array for custom hooks](https://twitter.com/dan_abramov/status/1140316424898043904). Expect consumers to call useCallback/useMemo if needed.
- [ ] [Support both Hooks and render props via the hydra pattern](https://americanexpress.io/hydra/)
- [ ] [React-async](https://docs.react-async.com/) and [react-query](https://github.com/tannerlinsley/react-query) for handling async and API calls
- [React Hook Form](https://react-hook-form.com/) - Custom hook for forms

## JSX in Depth

- [ ] [Spread attributes](https://reactjs.org/docs/jsx-in-depth.html#spread-attributes)
- [ ] [Booleans, null, undefined are ignored](https://reactjs.org/docs/jsx-in-depth.html#booleans-null-and-undefined-are-ignored)
- [ ] [Children](https://reactjs.org/docs/jsx-in-depth.html#children-in-jsx)
- [ ] [Passing props to children](https://frontarm.com/james-k-nelson/passing-data-props-children/)
- [ ] Demo: Create Card component that displays text inside a box with an optional title. Can also show ["slots" pattern](https://daveceddia.com/pluggable-slots-in-react-components/).
- [ ] [Example BlueBox component](https://codesandbox.io/s/thirsty-davinci-u1088) created as both a slot component and a compound component
- [ ] Pass component as prop (aka slots)
- [ ] [Create app `Layout` component](https://gist.github.com/coryhouse/1dad68883620354023bd718f93f21093) - This can hold your header, footer, context provider(s), scenario selector.

## Key Advanced Features

### Context

- [ ] [Context](https://reactjs.org/docs/context.html) - For "global" data.
- [ ] [How to use context effectively by Kent C Dodds](https://kentcdodds.com/blog/how-to-use-react-context-effectively)
- [ ] Avoid overuse - [Child composition eliminates prop drilling](https://www.youtube.com/watch?v=3XaXKiXtNjw&ck_subscriber_id=360118854) (or, think "slots" if multiple children). [Good example of composing children from Kent](https://epicreact.dev/one-react-mistake-thats-slowing-you-down/)
- [ ] i18n, user data, theme, auth
- [ ] It's been around since the creation of React (and used by React Router and Redux), [but not stable until 16](https://reactjs.org/docs/context.html#legacy-api).
- [ ] Context does NOT have to be global to the whole app.
- [ ] [Use context to disallow nesting a component under itself, or under another interactive element](https://www.aleksandrhovhannisyan.com/blog/react-context-nested-components/)
- [ ] You can have multiple logically separated contexts in your app.
- [ ] [Wrap provider and consumer to enforce certain usage and enhance performance](https://kentcdodds.com/blog/how-to-use-react-context-effectively) and [here](https://kentcdodds.com/blog/application-state-management-with-react)
- [ ] Wrap consumer in hook for convenient consumption. [useAlert example](https://gist.github.com/coryhouse/254595cf20a3b1ffbedce44aa7259f42). Just import useX and you have access. No need to import context and pass it to a useContext call. And can enforce that it's being called under a provider (as shown in link above)
- [ ] [Optimize your context value if perf is an issue](https://kentcdodds.com/blog/how-to-optimize-your-context-value)
- [ ] Redux remains useful. Redux offers scalable unidirectional flows, decomposed state handling via dedicated reducers and actions, hot reloading, time travel, and potential performance benefits via selectors and connect's reference comparison. Though can consider [react-waterfall](https://github.com/didierfranc/react-waterfall) to get most these benefits (albeit without Redux's huge ecosystem and excellent docs).
- [ ] Perf tip: As usual, avoid declaring objects in render since they're recreated on every render which causes needless rerenders. Instead, [declare the object passed down via context in state](https://reactjs.org/docs/context.html#caveats). More [here]( https://blog.kentcdodds.com/migrating-to-reacts-new-context-api-b15dc7a31ea0) under "Issues with the New API". Can put methods in state too. Or, you can [memoize the function](https://twitter.com/kentcdodds/status/995531525423677440)
- [ ] You can [require a parent provider with a simple pattern](https://gist.github.com/kentcdodds/5156fd21595e227819a4d2011fe51822) too.
- [ ] 3 ways to consume:
- [ ] [useHook](https://reactjs.org/docs/hooks-reference.html#usecontext) (prefer)
- [ ] [Consumer via render prop / child as func](https://reactjs.org/docs/context.html#contextconsumer)
- [ ] [Static contextType](https://reactjs.org/docs/context.html#classcontexttype) (classes only, and can only consume one context this way unless you wrap the others. Bottom line, prefer useHook)
- [ ] Connected components re-render when any values passed to the provider's value prop change. So don't declare the value in render. [Instead, lift it to state](https://reactjs.org/docs/context.html#caveats).
- [ ] [Require context](https://gist.github.com/kentcdodds/5156fd21595e227819a4d2011fe51822)
- [ ] [Updating context from the consumer](https://reactjs.org/docs/context.html#updating-context-from-a-nested-component) - However, consider passing dispatch and using useReducer instead since that may be preferable.
- [ ] [Consuming multiple contexts](https://reactjs.org/docs/context.html#consuming-multiple-contexts)
- [ ] [Create dedicated "store" component that holds provider](https://codesandbox.io/s/jvky9o0nvw)
- [ ] For performance, [you likely want to wrap the component directly under your context provider in React.memo](https://twitter.com/sophiebits/status/1228942768543686656) or use {props.children} - This means changes to the context value will rerender only the components consuming the context instead of the entire subtree. More [here](https://blog.isquaredsoftware.com/2020/05/blogged-answers-a-mostly-complete-guide-to-react-rendering-behavior). Here's a [codesandbox](https://codesandbox.io/s/laughing-knuth-wu9tm?file=/src/App.js) showing how to memo children.

### Refs

- [ ] Think of refs on React elements as functions that are called after the component has rendered
- [ ] Use `useCallback` with a ref to run some logic when the ref's target changes. [useCallbackRef example](https://tkdodo.eu/blog/avoiding-use-effect-with-callback-refs))
- [ ] [React docs](https://reactjs.org/docs/refs-and-the-dom.html)
- [ ] Prone to abuse. Avoid - you may not need it. Can be misused to manually change the DOM.
- [ ] 3 common valid uses:
- [ ] 1. Read and change DOM: focus, and calculate size and position.
- [ ] 2. Hold values not used in render in func components (can use instance vars in classes).
- [ ] 3. Forward refs to leaf nodes to support programmatically setting focus on elements. Useful for alerts, dialogs, textInputs. This way when something new appears/changes, you can programmatically focus the element.
- [ ] [Detailed blog post "The Complete Guide to React Refs"](https://rafaelquintanilha.com/the-complete-guide-to-react-refs)
- Refs are basically a special case of useState that doesn't trigger a re-render
- Set its value directly (instead of using a setter) via `myRef.current = 'val here'`
- Get value via `.current` property: `myRef.current`
- 4 approaches - [cheatsheet](https://react-refs-cheatsheet.netlify.com/):
- [ ] String refs (deprecated)
- [ ] Callback refs (clunkier syntax than createRef, but can be preferable when dealing with dynamic refs - otherwise prefer createRef or useRef below)
- [ ] createRef (Classes only - simpler syntax than callbacks)
- [ ] useRef (Funcs only) [UseRef is basically this](https://twitter.com/dan_abramov/status/1099842565631819776?s=21)

### Other Advanced Features
- [ ] [Render outside the parent's DOM via Portals](https://reactjs.org/docs/portals.html) - [Simple example](https://codesandbox.io/s/6yx5o1qpz)
- [ ] Capture scroll position before render using [getSnapshotBeforeUpdate](https://reactjs.org/docs/react-component.html#getsnapshotbeforeupdate). snapshot is the third param passed to componentDidUpdate.
- [ ] [Strict mode](https://reactjs.org/docs/strict-mode.html) - [Example](https://codesandbox.io/s/y2rj36w7l1)

## State

- [ ] Use instance vars for data that's not used in render
- [ ] [useMutableReducer hook for immer](https://twitter.com/aweary/status/1055517146942386177?s=21)
- [ ] Performing optimistic UI updates
- [ ] [Can declare lazy initial state for `useState` by passing it a func](https://reactjs.org/docs/hooks-reference.html#lazy-initial-state). Then the initial value isn't calculated only on initial render. (Plain default values are executed on page load when the component is parsed).
- [ ] [Place state as low as you can for performance](https://twitter.com/dan_abramov/status/1140273129916436481?s=21). Avoids needless re-renders.
- [ ] Keep state in sync with props via [getDerivedStateFromProps](https://reactjs.org/docs/react-component.html#static-getderivedstatefromprops)
- [ ] [Use functional setState to get prevState](https://medium.freecodecamp.com/functional-setstate-is-the-future-of-react-374f30401b6b#.47r5k656u) - [Codepen](https://codepen.io/mrscobbler/pen/JEoEgN) - Why? It's safe because when React encounters multiple functional setState() calls, instead of merging objects together, React queues the functions in the order they were called.
- [ ] [Extract setState calls for reuse and easy testing](https://twitter.com/dan_abramov/status/824308413559668744) - Declarative. Your component class no longer cares how the state updates. It simply declares the type of update it desires.
- [ ] [Init state without a constructor](http://stackoverflow.com/questions/35662932/react-constructor-es6-vs-es7)
- [ ] [Avoid state that can be calculated on demand](http://brewhouse.io/blog/2015/03/24/best-practices-for-component-state-in-reactjs.html)
- [ ] Avoid mutating state - remember to clone before mutation. [Mutation fights performance enhancements like sCU and PureComponent](https://medium.freecodecamp.org/why-arrow-functions-and-bind-in-reacts-render-are-problematic-f1c08b060e36)
- [ ] Deep cloning via [clone-deep](https://www.npmjs.com/package/clone-deep), [LoDash merge](https://lodash.com/docs/#merge)
- [ ] [Lift state](https://reactjs.org/docs/lifting-state-up.html)
- [ ] Controllable components
- [ ] [State reducer](https://buttondown.email/kentcdodds/archive/e4931c12-9bc3-4e86-85b5-e777e6126053) - Allow parent to augment/override the behavior of a child component by passing down a few props, or a reference to a single reducer. [Simple example](https://www.dropbox.com/s/asplyf19nxh4uv4/Screenshot%202019-07-04%2006.52.02.png?dl=0)
- [ ] [Avoid calling setState on unmounted components by cancelling any async work (use a var if only checked in useEffect. Use a ref if needs be checked outside of useEffect - see my follow up tweet](https://twitter.com/housecor/status/1093140100471492608?lang=en) Or, here's [Kent's codesandbox for class components and Axios](https://codesandbox.io/s/nwwrrpvqw4).
- [ ] Suggestion: Treat state as immutable: React lets you use whatever style of data management you want, including mutation. However, if you can use immutable data in performance-critical parts of your application it's easy to implement shouldComponentUpdate()/PureComponent to speed up your app.
- [ ] [Value equality vs Reference equality](https://blog.logrocket.com/immutability-in-react-ebe55253a1cc) - Summary: Value equality checks on objects and arrays is expensive. Reference equality checks are cheap. For value equality, you'd have to [implement it yourself](http://adripofjavascript.com/blog/drips/object-equality-in-javascript.html) or use Lodash's _.isEqual.
- [ ] [Four immutable approaches](https://medium.freecodecamp.org/handling-state-in-react-four-immutable-approaches-to-consider-d1f5c00249d5)
- [ ] [Example of the impacts of mutation with PureComponent)(https://codesandbox.io/s/mo57vnl7x9)
- [ ] Adding element to array? Use prevState.concat(newElement).
- [ ] Changing existing element in an array? [Use map and substitute the new value while iterating](https://www.dropbox.com/s/g29uf34z1t8w2om/Screenshot%202018-05-08%2020.09.20.png?dl=0).
- [ ] Removing an element from an array? Use .filter.
- [ ] Or just use something like Immer. [Many alternatives listed in Redux docs](https://redux.js.org/introduction/ecosystem#immutable-update-utilities)
- [ ] [Higher order event handlers / partial application](https://twitter.com/swyx/status/1039405539258597376?s=11)

## Props

- [ ] Support passing either a string or a React component. Useful for wrapping a string in an H1 by default, but allowing someone to pass an optional component in instead for more power. Use [React.isValidElement ](https://reactjs.org/docs/react-api.html#isvalidelement) to determine if a React element has been passed in on props. Note that you output the component passed on props a var, NOT as JSX. `{React.isValidElement(heading) ? heading :

{heading}

}`
- [ ] [Export enum from component when there's a finite list of options for a given prop](https://twitter.com/housecor/status/1111687761843703808)
- [ ] [Use classnames to support mixing additional class with built in class](https://www.dropbox.com/s/6z8ga59u7cizv1k/Screenshot%202019-07-04%2007.04.08.png?dl=0)
- [ ] Passing many props through many components?
- [ ] Consider passing an object if they're related
- [ ] Declare in parent and pass down as a child. Accepting children increases flexibility and [reduces prop drilling](https://twitter.com/dan_abramov/status/1021850499618955272?s=21). This pattern can also avoid needless re-renders (see "Pass component down as prop to avoid re-render" under performance below).
- [Spread props](https://reactjs.org/docs/jsx-in-depth.html#spread-attributes). Pass through props via destructuring:  `const { roleId, locks, ...passThroughProps} = props;`
- [ ] Declare shapes
- [ ] [Centralize propTypes](https://medium.freecodecamp.org/react-pattern-centralized-proptypes-f981ff672f3b)
- [ ] Avoid blindly creating defaultProps for all props. This leads to components that fail to warn you about missing props, and instead, do nothing.
- [ ] [Props default to true](https://reactjs.org/docs/jsx-in-depth.html#props-default-to-true)
- [ ] [Create a combine function to blend a func passed in on props with the components's built in behavior](https://www.dropbox.com/s/f9ibmcx734imppf/Screenshot%202019-07-04%2007.02.10.png?dl=0)
- [ ] [Require all props at first](https://twitter.com/housecor/status/987349452871602176)
- [ ] Declare propTypes and defaultProps via statics
- [ ] [Destructure props in functional component args](https://twitter.com/housecor/status/942946111739789313), or top of render in class components
- [ ] [Other advanced destructuring examples](http://blog.jakoblind.no/next-level-es6-react/)
- [ ] [Destructure and optionally alias prop-types import to shorten propTypes declarations](https://twitter.com/housecor/status/942946111739789313)
- [ ] [Easily generate propTypes from JSON via transform.now.sh](https://transform.now.sh/)
- [ ] [Spread attributes](https://reactjs.org/docs/jsx-in-depth.html#spread-attributes) - [Example](https://www.carlrippon.com/writing-concise-react-components-with-destructure-assignment-and-spread)
- [ ] Standardize event handler naming
- [ ] PropTypes vs [TypeScript](https://www.typescriptlang.org/) and [Flow](https://flow.org/)
- [ ] [Pass props to children using cloneElement or renderProps](https://frontarm.com/james-k-nelson/passing-data-props-children/)

## Performance

- [ ] See more in dedicated issue: https://github.com/coryhouse/reactjsconsulting/issues/77
- [ ] [6 techniques for managing large datasets in React](https://twitter.com/housecor/status/1337073677893070849)
- [ ] [2020 Comparison of React perf vs competition](https://medium.com/javascript-in-plain-english/javascript-frameworks-performance-comparison-2020-cd881ac21fce)
- [ ] [Many ideas on React docs](https://reactjs.org/docs/optimizing-performance.html)
- [ ] [Use react-adaptive-hooks](https://github.com/GoogleChromeLabs/react-adaptive-hooks) to implement progressive enhancement for devices with different network, CPU, cores, and memory.
- [ ] [Pass component down as prop to avoid re-render](https://codesandbox.io/s/react-codesandbox-o9e9f). Here's the [slow version that re-renders](https://codesandbox.io/s/react-codesandbox-g9mt5). [More in Ken's blog post](https://kentcdodds.com/blog/optimize-react-re-renders). [More complex example](https://codesandbox.io/s/react-codesandbox-qtdob?from-embed)
- [ ] [React bails out of rendering children if the children haven't changed](https://twitter.com/sebmarkbage/status/1096115287781400576), so no sCU, memo needed.
- [ ] Store data in localStorage to allow offline use and speed subsequent re-renders
- [ ] [Use memo, ref, or pass a func to useState if the initial value calls an expensive func](https://medium.com/@_m1010j_/how-to-avoid-this-react-hooks-performance-pitfall-28770ad9abe0), otherwise, it will be calculated on each render.
- [ ] Extract child components for expensive portions (optimize when they render via React.memo).
- [ ] [Before you reach for memo](https://overreacted.io/before-you-memo)
- [ ] [Avoid declaring objects in render](https://medium.com/@awjre/avoid-declaring-objects-as-properties-passed-into-components-as-well-814487696e2). It creates a new object on every render. This includes when passing objects via props.
- [ ] Use React.memo to avoid needless re-renders [Demo](https://codesandbox.io/s/4xj5r7rq8x)
- [ ] Can use React.memo with context too, but need to ["lift" context consumer to parent](https://codesandbox.io/s/3yn69wj0w5). Remember, with context, all children of provider rerender when the provider component renders.
- [ ] [3 ways to memo context](https://github.com/facebook/react/issues/15156#issuecomment-474590693)
- Could I create one instance per page instead of one per row (e.g. Avoid tooltip per row on large table, or dialog per row on large table. Instead, create one and populate dynamically based on a row click/hover)
- Remove one item at a time from a row/feature until it renders fast to help find the culprit.
- [ ] [Demo of React.memo and useCallback](https://medium.com/@sdolidze/react-hooks-memoization-99a9a91c8853). Also, check out scheduling performance example in [performance-tuning folder in this repo](https://github.com/coryhouse/rjc/tree/master/performance-tuning)
- [ ] See static rendering under Server Render below
- [ ] Change related state at the same time to avoid redundant renders
- [ ] Pass primitives (strings, numbers...) to child components to assist with diffing. Avoid passing arrow funcs and objects on props when performance is a concern since it leads to needless re-renders of child components.
- [ ] [React Lazy and Suspense](https://reactjs.org/docs/code-splitting.html#reactlazy), or consider [Loadable components](https://loadable-components.com/) if you want server-side support, library lazy loading, and full dynamic imports.
- [ ] [Suspense for data fetching](https://blog.logrocket.com/react-suspense-data-fetching/) - [Repo here](https://github.com/ovieokeh/suspense-data-fetching). Can also use [react-query in suspense mode](https://react-query.tanstack.com/guides/suspense) or [fetch-suspense](https://github.com/CharlesStover/fetch-suspense) (much less popular) or [react-fetching-library](https://codesandbox.io/s/4202lm924w, https://github.com/marcin-piela/react-fetching-library). Also see https://www.robinwieruch.de/react-hooks-fetch-data/, https://resthooks.io/.

Old alternatives to React.lazy:
- [ ] [react-loadable](https://github.com/jamiebuilds/react-loadable)
- [ ] [react-lazyload](https://github.com/jasonslyvia/react-lazyload)
- [ ] [react-lazy-load-fadein](https://react-lazyload-fadein.now.sh)
- [ ] [react-content-loader](http://danilowoz.com/react-content-loader/)
- [ ] [react-ideal-image](https://github.com/stereobooster/react-ideal-image/blob/master/introduction.md)
- [ ] [react-progressive-loader](https://github.com/yosbelms/react-progressive-loader) (Load images and components when scrolled into view)
- [ ] [Even more options listed here, some that support server rendering](https://hackernoon.com/react-and-code-splitting-made-easy-f118befb5168)
- [ ] [Cache React event listeners](https://medium.com/@Charles_Stover/cache-your-react-event-listeners-to-improve-performance-14f635a62e15)
- [ ] Use [plop](http://plopjs.com) or [hygen](https://github.com/jondot/hygen) to make lazy loading components easy. [react-boilerplate example](https://github.com/react-boilerplate/react-boilerplate/tree/master/internals/generators)
- [ ] Note cost:
- [ ] Trading static for dynamic, so reduced safety and autocomplete support.
- [ ] Adds decision fatigue.
- [ ] Adds latency.
- [ ] Adds complexity.
- [ ] Easy to get wrong by accidentally statically importing the component elsewhere. Consider writing tests that assert lazy loaded components aren't part of bundle. But that's extra work too.
- [ ] Lazy load libraries via [webpack dynamic imports](https://webpack.js.org/guides/code-splitting/#dynamic-imports)
- [ ] [why-did-you-render](https://github.com/welldone-software/why-did-you-render) - inspired by [Why did you update](https://github.com/maicki/why-did-you-update) - Find unnecessary renders
- [ ] Consider shouldComponentUpdate/PureComponent. Why? When you call setState, React will compare the old React elements to a new set of React elements (this is called [reconciliation](https://reactjs.org/docs/reconciliation.html)) and then use that information to update the real DOM elements. Sometimes that can get slow if you’ve got a lot of elements to check (like a big table, list, or SVG). [But only use after measuring result](https://cdb.reacttraining.com/react-inline-functions-and-performance-bdff784f5578). [Here's how to measure](https://reactjs.org/blog/2016/11/16/react-v15.4.0.html#profiling-components-with-chrome-timeline). Don’t imagine “I bet that code is slow”. Write your code naturally. If there are performance problems, fix them. Do **not** PureComponent all the things. "I added PureRenderMixin to every component. My app got slower 🤔." - Ryan Florence Why? A component does one diff. A pureComponent does one or two diffs (props and state in shouldComponentUpdate, and then the normal element diff). So if a component usually changes when there’s an update, then a PureComponent will be doing two diffs instead of just one. This means it’s going to be slower usually but faster occasionally. So if most of your components change most of the time, your app will get slower by using PureComponent everywhere because you're doing two diffs instead of one.
- [ ] Binding
- [ ] [Binding Patterns - 5 Ways to handle the `this` keyword](https://medium.freecodecamp.org/react-binding-patterns-5-approaches-for-handling-this-92c651b5af56)
- [ ] Avoid bind in render
- [ ] Pluck data from event by querying form elements via `event.target.elements.fieldName.value` - [See SearchInput here](https://codesandbox.io/s/nxqmqyxld?from-embed). Or [extract child components to avoid binding](https://medium.freecodecamp.org/react-pattern-extract-child-components-to-avoid-binding-e3ad8310725e)
- [ ] Prefer constructor bind if there will be a massive number of instances. (otherwise, suggest class fields for convenience)
- [ ] [Use ESI to reduce DB calls by selectively caching pieces of the page via an HOC](https://twitter.com/housecor/status/984239691003236353)
- [ ] Call setState with null to avoid re-render when the relevant state hasn't actually changed. (useful when someone clicked a button that fires a setState call, but no state is actually changed.
- [ ] [Prerender with react-snap](https://web.dev/prerender-with-react-snap/) or with [react-snapshot](https://github.com/geelen/react-snapshot)
- [ ] Use selectors for Redux
- [ ] Normalize your Redux store
- [ ] Structure your Redux store by key for fast access
- [ ] Consider Preact, Inferno
- [ ] [List of perf related blog posts](https://github.com/markerikson/react-redux-links/blob/master/react-performance.md)
- [ ] [21 React Related Perf Tweaks](https://www.codementor.io/blog/react-optimization-5wiwjnf9hj)

## Forms

I recommend plain React. Here's a [poll](https://twitter.com/housecor/status/1083081213869518849). But, [many options](
https://github.com/enaqx/awesome-react#form). A few popular options:
- [ ] [Formik](https://jaredpalmer.com/formik)
- [ ] [React Final Form](https://github.com/final-form/react-final-form)
- [ ] [react-jsonschema-form](https://github.com/mozilla-services/react-jsonschema-form)

## Maintainability

- [ ] Cancelling async requests
- [ ] [Simple Hooks example](https://twitter.com/ryanflorence/status/1129487337375690752) or [funny, yet clear alternative](https://twitter.com/mjackson/status/1129510187402911744)
- [ ] [Use date / promise comparison, or AbortController](https://twitter.com/ryanflorence/status/1064927423160963072). [My abortcontroller example](https://twitter.com/housecor/status/1531266357572034565)
- [ ] Use [Barrel pattern](https://basarat.gitbooks.io/typescript/docs/tips/barrel.html) to shorten imports
- [ ] Centralized form change handers
- [ ] When to consider creating a new component
- [ ] To support reuse of a portion
- [ ] Mixing complex logic and presentation
- [ ] To avoid re-rendering an expensive portion
- [ ] Repetition in JSX - Just create a func inside a component instead if separate component isn't needed
- [ ] Displaying unrelated data
- [ ] Handling unrelated logic
- [ ] [Folder structure](https://hackernoon.com/tips-on-react-for-large-scale-projects-3f9ece85983d)
- [ ] [Component folder pattern](https://medium.com/styled-components/component-folder-pattern-ee42df37ec68)
- [ ] [Organize component folders to mimic routing path](https://hackernoon.com/structuring-projects-and-naming-components-in-react-1261b6e18d76). Place reusable components in /UI. Don't repeat the path name in the component's name, but when importing, alias the default to reflect the import path. Example: `import UserList from './User/List.js';`
- [ ] [The "brick" pattern at eBay](https://technology-ebay-de.github.io/breaking-down-your-react-app/#/35) - [Folder structure](https://technology-ebay-de.github.io/breaking-down-your-react-app/#/34). [All the things in a brick](https://technology-ebay-de.github.io/breaking-down-your-react-app/#/47)
- [ ] Centralized change handler
- [ ] Transform HTML to JSX using [transform.now.sh](https://transform.now.sh/)
- [ ] [Separate logic and layout](https://technology-ebay-de.github.io/breaking-down-your-react-app/#/21)
- [ ] [Container vs Presentation components](https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0) (aka smart vs dumb)
- [ ] Use Stateless components for dumb components?
- [ ] [The good parts](https://hackernoon.com/react-stateless-functional-components-nine-wins-you-might-have-overlooked-997b0d933dbc)
- [ ] [The bad parts](https://medium.freecodecamp.org/7-reasons-to-outlaw-reacts-functional-components-ff5b5ae09b7c)
- [ ] [Conditionals in render](https://reactjs.org/docs/conditional-rendering.html) - [Many options](https://blog.logrocket.com/conditional-rendering-in-react-c6b0e5af381e)
- [ ] Ternary
- [ ] Logical &&, || in render - [Can combine func call with && too](https://gist.github.com/rajatgeekyants/ef1e6eb8c4d1eff4a399e16539a602e6#file-conditional-js)
- [ ] Multiple return/return early
- [ ] [Component composition](https://reactjs.org/docs/composition-vs-inheritance.html)
- [ ] [props.children](https://reactjs.org/docs/composition-vs-inheritance.html#containment)
- [ ] [Specialization](https://reactjs.org/docs/composition-vs-inheritance.html#specialization)
- [ ] Branch pattern
- [ ] [Higher order components](https://codesandbox.io/s/kk7omkwno5)
- [ ] [Manually set the displayName for clearer debugging in the console](https://reactjs.org/docs/higher-order-components.html#convention-wrap-the-display-name-for-easy-debugging)
- [ ] [Create HOC from render prop component](https://twitter.com/kentcdodds/status/989711303659765760)
- [ ] [Render props / function as child](https://codesandbox.io/s/o5x4yx7725)
- [ ] [Compose render props together elegantly](https://github.com/pedronauck/react-adopt)
- [ ] Compound components
- [ ] [Simple example that uses IDs](https://codesandbox.io/s/2xm5kvvv6n)
- [ ] [Opinionated example - can only use string for label](https://codesandbox.io/s/zq99pwrlm)
- [ ] [Advanced example that uses cloneElement to avoid IDs, but at expense of more wrapper elements and implementation complexity](https://codepen.io/coryhouse/pen/RvpWzm)
- [ ] [Ryan Florence's composition examples](https://ryanflorence.dev/p/advanced-element-composition-in-react) with 4 different levels of complexity
- [ ] Formatting/styling components
- [ ] [Integrate React into an existing app](https://frontarm.com/articles/how-to-integrate-react-into-existing-app/)
- [ ] [The 8 Key React Component Decisions](https://medium.freecodecamp.org/8-key-react-component-decisions-cc965db11594)
- [ ] [Common mistakes](https://dev.to/samerbuna/reactjs-frequently-facedproblems--l5g)
- [ ] [More common mistakes from Elijah Manor](https://gist.github.com/elijahmanor/778c8effcd62db9a1a5a78899fdd68de)

## Debugging

- [ ] debugger keyword
- [ ] Use [react-dev-tools](https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi?hl=en)
- [ ] console.log accepts multiple params
- Use with concise arrow syntax in functional components that use parens for render
- Easily format output to the console
- console.table
- console.assert
- [Use logical or to force conditionals to true](https://twitter.com/wesbos/status/994589323294060546?s=21) (helpful to force ongoing display of loaders that go away quickly)
- [ ] [JSX IIFE Debugger pattern](https://twitter.com/_ericelliott/status/974866657322479616?s=21)

## Server Rendering
- [ ] [Render to static files](https://facebook.github.io/create-react-app/docs/pre-rendering-into-static-html-files)
- [ ] [Static site generators like Gatsby, Next, etc](https://blog.bitsrc.io/9-react-static-site-generators-for-2019-f54a66e519d2)
- [ ] Prerender.io
- [ ] [Comprehensive blog post](https://medium.freecodecamp.org/server-rendering-with-react-and-react-router-e0b7ba37653f) (summary: It's complicated)
- [ ] [Rogue](https://github.com/alidcastano/rogue)
- [ ] [Example repo](https://github.com/tylermcginnis/rrssr)

## Deployment
- [ ] If users leave their tab open for days/weeks, they may request an old file when they click a link. Avoid users getting errors by requesting an old file that's no longer deployed by including the site version in a cookie. Use that to say "A new version of the site is available. Click OK to reload the site." as suggested [by Rich Harris](https://dev.to/richharris/in-defense-of-the-modern-web-2nia).

## More?
- [ ] Show and tell! What patterns have you found useful?

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.