React hooks

Hooks are a new way of creating stateful components without classes. you can use hooks only on the body of the components or the body of other hooks and you cannot use them on helper functions or inside other functions.

useState

useState hook returns two objects like this:

const [data, setData] = useState({a: 1, b: 2});

Consider you want to change only b to 3. You can obviously do the following:

setData({
    ...data,
    b: 3
})

But the problem with the above code is that it depends on the data object and it could be an issue especially if you want to set the state inside a useMemo or useEffect since you have to add the data as the dependency of your hook which makes that hook to trigger on each change which is not desired all the times. To avoid that you can use the following overload which doesn't rely on the data object:

setData(oldData => {
    ...oldData,
    b: 3
})

useRef

We use this hook whenever we don't want React to create a new object every time it rerenders. For example, if I know that a method in my component returns an object which is not going to change over rerenders I can wrap it in a useRef hook and react will know that this is an object which is not going to change over rerenders hence I don't need to list it in the dependency list of useEffect or useMemo hooks.

const callMeRef = useRef(getCallMeFunction());

useEffect(() => {
    callMeRef.current();
});

useMemo

We use this hook for the code that we need to run once. For example, if we are doing some calculations or bindings which we want to do once and only when the dependencies have changed we can wrap that piece of code inside a useMemo hook.

useMemo(() => {
    bindTableData();
})

useEffect

This hook can be used as a replacement for componentDidMount and componentDidUpdate. If the dependency array is not provided, then it'll act as both methods which means it'll run first on "mount" and then on every re-render. If the dependency array is an empty array, it acts like componentDidMount only and will only run once. However, it's not a good practice to omit dependencies just to make useEffect to act like componentDidMount since all the variable objects inside the body of the hook should be listed otherwise some unexpected behaviour could happen and it's hard to find the culprit if we don't follow this practice. If you need to omit something from the dependency array you can use other methods like using useRef hook to make that object fix during re-renders. Lastly, if there are items in the dependency array, then it'll run on "mount" and also whenever that particular variable changes.

Please note that if the dependency is an object then the object reference must be changed to trigger the side effect not the properties of that object.

Normally in a component, you want to have multiple useEffect hooks, one for each side effect with a different set of dependencies.

useContext

You may use this hook if you want to share a value with other components without passing that directly to all other components. It's useful for passing config and shared values within a project.

useReducer

You use this hook for managing the local state of a component similar to what useState does. The difference here is that you can trigger actions on that component from anywhere not just from the component itself.