Free React Course
For Beginners

L3 - React with Hooks

React For Beginners by Itera

Key Points

  • What is a hook
  • Hook rules
  • UseState
  • Use Effect
  • UseContext
  • Custom hooks

What is a hook

Hook as is just a function, that

  • Starts with use
  • Lives only inside functional component or other hooks

Hooks extends functional components functionality

Hooks allows you to have state, hook into lifecycle, share functionality

Appeared since React 16.8

Started from very arguable, now almost the standard

Pros

  • Extends functional components functionality
  • Very nice way to share common logic

Cons

  • Might become extremely messy

Hook rules

Name hook with use

  • useState()
  • useCallback()
  • useWhatEverYouWant()

Use only inside functional component or other hook

Don't use conditionally or in loops

React relays on the order of hook invocations

Use as much hooks (even the same) as you need

Most useful hooks

UseState

useState allows you to have smart functional components

const App = () => {
  const [state, setCounter] = useState(0);
  return (
    <button onClick={() => setCounter(state + 1)}>
      Increment: {state}
    </button>
  );
};
    

Important! Don't mutate the state!

const WrongApp = () => {
  const [state, setState] = useState({ isAdmin: false });

  const assignAdmin = () => {
    state.isAdmin = true; // WRONG
    setState(state);
  };

  return <button onClick={assignAdmin}>Assign admin</button>;
};

You need to create new instance instead

const WrongApp = () => {
  const [state, setState] = useState({ isAdmin: false });

  const assignAdmin = () => {
    setState({ ...state, isAdmin: true }); // CORRECT
  };

  return <button onClick={assignAdmin}>Assign admin</button>;
};

For more advanced cases you might want to look into useReducer hook

UseEffect

useEffect allows you to hook into lifecycle

Component did update

Debugging, logging or measuring


       useEffect(() => console.log("component invoked"));
    

Component did mount

Calls to the server, initialization


      //note second argument
      useEffect(()=> {console.log('one time action')}, []);
    

Component did update and dependency changed

Recall when the value changed

 
  useEffect(() => console.log("component invoked"), [dependency]);
    

Component will unmount

Cleanup the resources like timers or pending requests


      useEffect(() => {
        ... // logic
        return ()=> console.log('cleaning ...');
      });
    

UseContext

useContext allows you easily access the context

Create context first

import { createContext } from "react";

const defaultValue = { name: "Vitalii", isAdmin: true };
const UserCtx = createContext(defaultValue);

Provide context into the React application

const App = () => {
  return (
    <UserCtx.Provider value={defaultValue}>
      <h1>This is my app</h1>
      <AboutUser />
    </UserCtx.Provider>
  );
};

UseContext from any functional component

const AboutUser = () => {
  const { name, isAdmin } = useContext(UserCtx);
  return (
    <div>
      UserName: {name}, isAdmin: {isAdmin}
    </div>
  );
};
    

UseCallback

useCallback - returns the same function unless dependencies changed

Use case

type WithCallback = { callback: () => void };

class ExpensiveComponent extends PureComponent<WithCallback> {
  render() { return <div>Expensive</div>; }
  componentDidUpdate() { console.log("updated"); }
}
      

The issue

const App = () => {
  const [state, setState] = useState(0);
  const callback = ()=> {};
  return (
    <>
      <ExpensiveComponent callback={callback} />
      <button onClick={() => setState(state + 1)}>
        Increment: {state}
      </button>
    </>
  );
};
    

The solution

const callback = useCallback(() => {}, []);
    

Custom hooks

Simplify interface and hide the logic inside the hook

const useCounter = (defaultValue: number) => {
  const [state, setState] = useState(defaultValue);
  const increment = useCallback(
    () => setState(state + 1), 
    [state]);
  return { state, increment };
};

Usage is the same- but easier

const App = () => {
  const { state, increment } = useCounter(0);
  return (
      <button onClick={increment}>Increment: {state}</button>
  );
};

Takeaway

  • Hook - a modern to API to functional components
  • Most useful are useState, useEffect
  • You can write your own hooks

Useful links

Join me

Twitter
GitHub