/mar30-w07d03

Lecture notes and example code for Week 7 Day 3 lecture.

Primary LanguageJavaScript

W7D3 - Side Effects & Other Data Fetching

To Do

  • Rules for Hooks
  • Pure Functions and Side Effects
  • useEffect
  • Dependencies
  • Cleanup
  • useEffect Flow

Two Rules for Hooks

  1. Don't call Hooks inside loops, conditions, or nested functions. Always use Hooks at the top level of your React functions
  2. Only call Hooks from React functions.

Pure Functions

  • A function is said to be pure if:
    • It produces no side-effects
    • It will return the same value if called with the same arguments
// simple pure functions
const add = (num1, num2) => {
  return num1 + num2;
};

const sayHello = (name) => {
  return `Hello there ${name}!`;
};

Side Effects

  • Any operation that modifies the state of the computer or interacts with something outside of your program is said to have a side effect
  • Common side effects:
    • Writing to standard out (eg. console.log)
    • Modifying the DOM directly (instead of relying on React)
    • Establishing socket connections (eg. ws or Socket.io)
    • Retrieving data from an API (eg. axios, jQuery, or the fetch API)
    • Setting timers or intervals

useEffect

  • useEffect is a Hook we can use to deal with side effects in our components
  • The effect hook fires after the browser has painted the DOM
  • Multiple effect hooks can be used inside of a single component to group similar operations together
const MyComponent = (props) => {
  const [user, setUser] = useState({});

  useEffect(() => {
    // retrieve user information from an API and update local state with the response
    fetch(`/users/${props.userId}`)
      .then(res => res.json())
      .then(json => setUser(json));
  });

  return (
    <div className="my-component">
      <p>You are logged in as { user.username }</p>
    </div>
  );
};

Dependencies

  • The second argument to useEffect is a dependency array that lets you specify when you want the hook to run
  • The hook will run again anytime the value of a dependency changes
  • NOTE: It is possible to get stuck in an infinite loop if the effect hook updates a value in the dependency array
  • If you want a useEffect hook to only run one time, pass it an empty dependency array ([])
// will run every time the value of user.firstName changes
useEffect(() => {
  document.title = `${user.firstName}'s Home Page`;
}, [user.firstName]);

// only runs once
useEffect(() => {
  fetch(`/users/${props.userId}`)
    .then(res => res.json())
    .then(json => setUser(json));
}, []);

// infinite loop because it runs every time count gets updated
useEffect(() => {
  setCount(count + 1);
}, [count]);

Cleanup

  • Sometimes side effects need to be cleaned up (eg. socket connections terminated)
  • To perform cleanup, return a function from your useEffect
const [timer, setTimer] = useState(0);

useEffect(() => {
  // set up an interval to increment a timer
  const myInterval = setInterval(() => {
    setTimer(timer => timer + 1);
  }, 1000);

  // declare a cleanup function
  const cleanup = () => {
    clearInterval(myInterval);
  };

  return cleanup;
}, []);

useEffect Flow

  1. React turns your JSX into HTML (client-side rendering) and updates the DOM
  2. The browser responds to the change by updating the UI
  3. Any cleanup for effects from the previous render are performed
  4. New effects for the current render are performed

useEffect flow

Useful Links