React – How to use Hook (1)?

Class vs Hooks

  • componentDidMount
useEffect(() => {
  // Your code here
}, []);
  • componentDidUpdate
useEffect(() => {
  // Your code here
}, [yourDependency]);
  • componentWillUnmount
useEffect(() => {
  // componentWillUnmount
  return () => {
     // Your code here
  }
}, [yourDependency]);

What is life cycle of useEffect?

import React, { useEffect, useState } from 'react';
import ReactDOM from 'react-dom';

function LifecycleDemo() {
  // It takes a function
  useEffect(() => {
    // This gets called after every render, by default
    // (the first one, and every one after that)
    console.log('render!');

    // If you want to implement componentWillUnmount,
    // return a function from here, and React will call
    // it prior to unmounting.
    return () => console.log('unmounting...');
  }, [ // dependencies to watch = leave blank to run once or you will get a stack overflow  ]);

  return "I'm a lifecycle demo";
}

function App() {
  // Set up a piece of state, just so that we have
  // a way to trigger a re-render.
  const [random, setRandom] = useState(Math.random());

  // Set up another piece of state to keep track of
  // whether the LifecycleDemo is shown or hidden
  const [mounted, setMounted] = useState(true);

  // This function will change the random number,
  // and trigger a re-render (in the console,
  // you'll see a "render!" from LifecycleDemo)
  const reRender = () => setRandom(Math.random());

  // This function will unmount and re-mount the
  // LifecycleDemo, so you can see its cleanup function
  // being called.
  const toggle = () => setMounted(!mounted);

  return (
    <>
      <button onClick={reRender}>Re-render</button>
      <button onClick={toggle}>Show/Hide LifecycleDemo</button>
      {mounted && <LifecycleDemo/>}
    </>
  );
}

ReactDOM.render(<App/>, document.querySelector('#root'));

What are differences between useEffect and useLayoutEffect?

useEffect

useEffect runs asynchronously and after a render is painted to the screen.

  1. You cause a render somehow (change state, or the parent re-renders)
  2. React renders your component (calls it)
  3. The screen is visually updated
  4. THEN useEffect runs

useLayoutEffect

useLayoutEffect, on the other hand, runs synchronously after a render but before the screen is updated. That goes:

  1. You cause a render somehow (change state, or the parent re-renders)
  2. React renders your component (calls it)
  3. useLayoutEffect runs, and React waits for it to finish.
  4. The screen is visually updated

When to use useEffect?

  • Fetching data is not going to result in an immediate change
  • Setting up an event handler
  • Resetting some state when a modal dialog appears or disappears

When to use useLayoutEffect?

If your component is flickering when state is updated because it renders in a partially-ready state first and then immediately re-renders in its final state.

import React, {
  useState,
  useLayoutEffect
} from 'react';
import ReactDOM from 'react-dom';

const BlinkyRender = () => {
  const [value, setValue] = useState(0);

  useLayoutEffect(() => {
    if (value === 0) {
      setValue(10 + Math.random() * 200);
    }
  }, [value]);

  console.log('render', value);

  return (
    <div onClick={() => setValue(0)}>
      value: {value}
    </div>
  );
};

ReactDOM.render(
  <BlinkyRender />,
  document.querySelector('#root')
);

useLayoutEffect only updates visually once even though the component rendered twice.

The useEffect version, on the other hand, visually renders twice, so you see a flicker where the value is briefly 0.

How to use “useReducer”?

reducer.js

export const initialState = {
    employeeDetail: null,
    photo: ''
}
  
export const reducer = (state, action) => {
    switch (action.type) {
        case 'SELECT_EMPLOYEE':
            return {
                ...state,
                employeeDetail: action.employeeDetail
            }
        case 'SET_PHOTO':
            return {
                ...state,
                photo: action.photo
            }
        default:
            return state
    }
}

actions.js

 export const setEmployeeDetail = (dispatch, employeeDetail) => {
        dispatch({
            type: 'SELECT_EMPLOYEE',
            employeeDetail: employeeDetail
        })
    }
 export const setPhoto = (dispatch, photo) => {
        dispatch({
            type: 'SET_PHOTO',
            photo: photo
        })
    }

react-component.js

import React, {useEffect, useReducer} from 'react'
...

const TemperatureForm = () => {
    const [state, dispatch] = useReducer(reducer, initialState)
    useEffect(() => {
        // Fetch data
        const employeeDetail ={...}
        setEmployeeDetail(dispatch, employeeDetail)
    }

    return <>
        <Text>{state.employeeDetail.name}</Text>
    </>
}

Be the first to comment

Leave a Reply

Your email address will not be published.


*