Skip to content

Instantly share code, notes, and snippets.

@shivam1283
Last active December 15, 2022 06:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shivam1283/d52a1bd6168ab799c3b65aacbcd12954 to your computer and use it in GitHub Desktop.
Save shivam1283/d52a1bd6168ab799c3b65aacbcd12954 to your computer and use it in GitHub Desktop.
React Concepts

What problems it solves?

HOC

Render props

wrapper hell

Reusing logic

Giant components

Class components are confusing and tricky

Advantages of JSX

Separation of concerns

React embraces the fact that rendering logic is inherently coupled with other UI logic: how events are handled, how the state changes over time, and how the data is prepared for display.

Instead of artificially separating technologies by putting markup and logic in separate files, React separates concerns with loosely coupled units called “components” that contain both.

JSX Prevents Injection Attacks

const title = response.potentiallyMaliciousInput;
// This is safe:
const element = <h1>{title}</h1>;

This safe in JSX. By default, React DOM escapes any values embedded in JSX before rendering them. Thus it ensures that you can never inject anything that’s not explicitly written in your application. Everything is converted to a string before being rendered. This helps prevent XSS (cross-site-scripting) attacks.

Babel with JSX

Babel compiles JSX down to React.createElement() calls.

const element = (
  <h1 className="greeting">
    Hello, world!
  </h1>
);

is converted to...

const element = React.createElement(
	'h1',
    {className: 'greeting'},
  'Hello world!')

React.createElement converts the above element into something like this,

// Note: this structure is simplified
const element = {
  type: 'h1',
  props: {
    className: 'greeting',
    children: 'Hello, world!'
  }
};

With JSX, it is easy to define UI components in React. JSX should not be implemented directly by browsers, but instead requires a compiler to transform it into ECMAScript. This is where Babel comes in. Babel acts as this compiler allowing us to leverage all the benefits of JSX while building React components.

InProgress

LazyLoading

Preventing rerenders

Memory Leaks

React.lazy and Suspense

shouldComponentUpdate(nextProps, nextState)

React.memo(function(){}, function areEqual(prevProps,nextProps){})

useEffect to trigger relavent sideEffect

useMemo and useCallback

useTransition and useDeferredValue

Syntax:

shouldComponentUpdate(nextProps, nextState){
	//compare current and next props and state
    // return false if re-render not required
}

Use shouldComponentUpdate() to let React know if a component’s output is not affected by the current change in state or props.

  • PureComponent is exactly the same as Component except that it handles the shouldComponentUpdate method for you.
  • shouldComponentUpdate is called for both Component and PureComponent if explicitely implemented in the code.
  • but PureComponent calls shouldComponentUpdate implicitely (if not implemented by component itself) and does a shallow comparison of props and state.
  • If a component is PureComponent, make sure all the children components are Pure.Component as well??
  • If shouldComponentUpdate returns false UNSAFE_componentWillUpdate(), render(), and componentDidUpdate() will not be called.
  • React doesn't check the props and state itself: firstly, the performance savings of skipping render may be negligible compared to analyzing props and state.
  • Secondly, doing the comparison is not exactly straight-forward. Is your prop a primitive?, an Immutable?, an array?, a complex object?, will a deep compare be necessary?
  • React's model is "We will render everything asked by default. If you want something to opt-out for performance, then go ahead and tell us by implementing shouldComponentUpdate".
  • You should go for React.PureComponent when you can satisfy any of the below conditions.
    • State/Props should be an immutable object
    • State/Props should not have a hierarchy
    • You should call forceUpdate when data changes

PureComponent application

Shallow Comparison 101

When comparing previous props and state to next, a shallow comparison will check that primitives have the same value (eg, 1 equals 1 or that true equals true) and that the references are the same between more complex javascript values like objects and arrays.

Never MUTATE

You’ve probably been hearing not to mutate objects and arrays in props and state. If you were to mutate objects in a parent component, your “pure” child components wouldn’t update. Although the values have changed upstream, the child would be comparing the reference to the previous props and not detect a difference.
Instead, return new objects when you make a change by either leveraging es6 for object and array spreading or using a library to enforce immutability.

Don’t bind values in functions in render

Say you have a list of items, each passing a unique parameter to parent method. In order to bind the parameter you’ve maybe done something like this:

<CommentItem likeComment={() => this.likeComment(user.id)} />

The problem is that every time the parent’s render method is called, a new function (with a new reference) is created to be passed to likeComment. This has the side effect of changing the props on each child which in turn will cause them all to re-render, even if the data itself is all the same.

To get around this, only pass the reference to the parent’s prototype method to children. The child’s likeComment prop will always have the same reference and never cause a needless re-render.

<CommentItem likeComment={this.likeComment} userID={user.id} />

Then in the child component create a class method that will reference its props:

class CommentItem extends PureComponent {
  ...
  handleLike() {
    this.props.likeComment(this.props.userID)
  }
  ...
}

Don’t derive data in the render method

Consider a list of articles from which your profile component will display the user’s 10 most liked pieces.

render() {
  const { posts } = this.props
  const topTen = [...posts].sort((a, b) => 
    b.likes - a.likes).slice(0, 9)
  return //...
}

topTen will have a brand new reference each time the component re-renders, even if posts hasn’t changed and the derived data is the same. This will then re-render the list needlessly.

You can solve this by caching your derived data. For example, Set the derived data in the component’s state and update only when the posts have updated.

componentWillMount() {
  this.setTopTenPosts(this.props.posts)
}
componentWillReceiveProps(nextProps) {
  if (this.props.posts !== nextProps.posts) {
    this.setTopTenPosts(nextProps.posts)
  }
}
setTopTenPosts(posts) {
  this.setState({
    topTen: [...posts].sort((a, b) => b.likes - a.likes).slice(0, 9)
  })
}

Sources

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