Combined with react’s effect hook to analyze the elimination of side effects of components

Time:2020-1-26

A component to subscribe to friends online

We subscribed to our friends’ online status through ID when we were in didmount
And to prevent memory leaks, we need to clear the subscription in willunmount

But what happens when the friend prop changes when the component is already on the screen? Our component will continue to show the original friend status. This is a bug. In addition, we will use the wrong friend ID when unsubscribing to cause memory leakage or crash.

class FriendStatus extends React.Component {
  constructor(props) {
    super(props);
    this.state = { isOnline: null };
    this.handleStatusChange = this.handleStatusChange.bind(this);
  }

  componentDidMount() {
    ChatAPI.subscribeToFriendStatus(
      this.props.friend.id,
      this.handleStatusChange
    );
  }

  componentWillUnmount() {
    ChatAPI.unsubscribeFromFriendStatus(
      this.props.friend.id,
      this.handleStatusChange
    );
  }

  handleStatusChange(status) {
    this.setState({
      isOnline: status.isOnline
    });
  }

  render() {
    if (this.state.isOnline === null) {
      return 'Loading...';
    }
    return this.state.isOnline ? 'Online' : 'Offline';
  }
}

Optimize the components of subscribing to friends online

In order to solve the bug caused by props update, we need to modify the subscription in didupdate

componentDidMount() {
    ChatAPI.subscribeToFriendStatus(
      this.props.friend.id,
      this.handleStatusChange
    );
  }

  componentDidUpdate(prevProps) {
    //Friend.id before unsubscribing
    ChatAPI.unsubscribeFromFriendStatus(
      prevProps.friend.id,
      this.handleStatusChange
    );
    //Subscribe to a new friend.id
    ChatAPI.subscribeToFriendStatus(
      this.props.friend.id,
      this.handleStatusChange
    );
  }

  componentWillUnmount() {
    ChatAPI.unsubscribeFromFriendStatus(
      this.props.friend.id,
      this.handleStatusChange
    );
  }

Effect Hook

UseEffect () allows you to perform side effects in function components
By default, it executes after the first rendering and after each update.

If you are familiar with the life cycle functions of react class, you can think of useeffect hook as a combination of three functions: componentdidmount, componentdidupdate and componentwillunmount.

This is the most basic hooks application of react official website

import React, { useState, useEffect } from 'react';

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

  // Similar to componentDidMount and componentDidUpdate:
  useEffect(() => {
    // Update the document title using the browser API
    document.title = `You clicked ${count} times`;
  });

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

Effect to be cleared

Why return a function in an effect? This is an optional cleanup mechanism for effect. Each effect can return a cleanup function. This brings together the logic of adding and removing subscriptions. They are all part of the effect.

When does react clear effect? React performs the cleanup operation when the component is uninstalled. As you learned earlier, effect is executed every time you render. This is why react cleans up the previous effect before executing the current effect.

import React, { useState, useEffect } from 'react';

function FriendStatus(props) {
  const [isOnline, setIsOnline] = useState(null);

  useEffect(() => {
    function handleStatusChange(status) {
      setIsOnline(status.isOnline);
    }

    ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
    // Specify how to clean up after this effect:
    return function cleanup() {
      ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
    };
  });

  if (isOnline === null) {
    return 'Loading...';
  }
  return isOnline ? 'Online' : 'Offline';

Now suppose props. Friend. ID is updating 100 – > 200 – > 300
We don’t need specific code to handle the update logic, because useeffect handles it by default. It cleans up the previous effect before calling a new one. This is based on the fact that no bug will be generated due to props changes

// Mount with { friend: { id: 100 } } props
Chatapi. Subscribetoffriendstatus (100, handlestatuschange); // run the first effect

// Update with { friend: { id: 200 } } props
Chatapi. Unsubscribefromfriendstatus (100, handlestatuschange); // clear the previous effect
Chatapi. Subscribetoffriendstatus (200, handlestatuschange); // run the next effect

// Update with { friend: { id: 300 } } props
Chatapi. Unsubscribefromfriendstatus (200, handlestatuschange); // clear the previous effect
Chatapi. Subscribetoffriendstatus (300, handlestatuschange); // run the next effect

// Unmount
Chatapi. Unsubscribefromfriendstatus (300, handlestatuschange); // clear the last effect

How to skip some unnecessary side effect functions

According to the idea in the previous section, these side-effect functions should be executed once for each re rendering, which is obviously uneconomical. How to skip unnecessary calculations? We just need to pass the second parameter to useeffect. Use the second parameter to tell react to execute the side effect function we passed (the first parameter) only when the value of this parameter changes.

useEffect(() => {
  document.title = `You clicked ${count} times`;
}, [count]; // only when the value of count changes will the sentence 'document. Title' be executed again

Extension: if you want to execute an effect that runs only once (only when the component is mounted and unloaded), you can pass an empty array ([]) as the second parameter. This tells react that your effect does not depend on any value in props or state, so it never needs to be repeated. This is not a special case – it still works in a way that relies on arrays.

Reference

  • https://react-1251415695.cos-…

Recommended Today

Mysql database table partition

Mysql database added partition support in version 5.1. The process of partitioning is to break down a table or index into smaller, more manageable parts. As far as the application of accessing database is concerned, logically speaking, there is only one table or index, but physically, the table or index may be composed of dozens […]