React Hooks The Rundown

React Hooks The Rundown

In late 2018 Facebook changed the face of React by adding in Hook, a new way to write apps wholely relying on functional components and with other libraries implementing hooks along with the core library now everything can be done using the new design.

We adopted hooks into our app not too long after Facebook pushed them out and with using them in production for at least a year at this point I believe everyone on the team has came around to them and finally we are seeing cleaner more self contained components.

Initally moving from the long lived React lifecycles that everyone knew and love such as ComponentDidMount, ComponentWillUpdate, ComponentWillUnmount which has been long standing staples within the React world and everyone learnt how to work with the, however just because they have been around for a long time doesn't mean they are the best especially the update lifecycle I usually found in bigger components that got convoluted and hard to understand which is why Hooks just improved everything

So Hook are a lot more declarative than the traditional lifecycles and allow you to modularise your code much more, and when you pull in Redux and React-Router-Dom hooks you start to have some pretty great self contained components.

const ItemComponent = () => {
	const [item, setItem] = useState({});
    
    useEffect(() => {
        const getItem = async () => {
	        const response = await fetch('exaple.com/api');
            const json = await response.json();
            setItem(json);
        }
    	getItem();
        return () => {
        	setItem({});
        }
    }, [])
    
    
    if(item.name){
        return (
            <div>
                <h1>{item.name}</h1>
            </div>
        )
    }
    return (<div>Loading...</div>)

}

The above example covers the new useState hook to set the local state in a much easier way then previously with the constructor of the class it is a bit easier to work with in my opinion. I am also using the useEffect to make an API request and then update the setItem as a result there is also a return function that is the same as component will unmount and allows for clean up, the above example is not really required but it is added just to prove the point for that.

Of course Facebook have some great documentation on hooks and it is well worth a read. But this is only the beginning of what hooks we can use as there is actually so many different hooks we can use in React now, which is pretty awesome, I'll go over the many others and explore them in a little detail.

React Hooks

Along withg the useState and useEffect hooks in React there are also a few more that are pretty useful.

The useContext hook allows us to work more with data passed through our app via the context interface. Context is a store of that the creates a provider in a similar way to Redux it however is more scoped to specific areas which means it can be useful when you have a large app and some local values that are shared between a large section. Context also comes in handy if you don't want to include Redux and for smaller apps this is indeed fairly standard. To use Context you have to wrap the component in the context provider.

const item = {name: 'an item', value: 100, text: 'more stuff'}
const ItemContext = React.createContext(item);

const App = () => (
	<ItemContext.Provider value={item}>
    	<OtherComponent />
    </ItemContext.Provider>
)

The useCallback hook provides an alternative use case from the standard useEffect by using memorization to help prevent unnecessary rerenders of the memorized item. The idea is it will only update and rerender if one of the dependancies have also been updated, this is useful for expensive operations.

const memoized = useCallback(() => {aFunction(x)}, [x]);

The useMemo hook acts in a similar way to that of useCallback and useEffect as it will also only recompute once a dependacy has been updated, however when no dependancy is passed it will recompute on each render cycle. The main difference between useMemo and useEffect is useEffect will cause side effects where as useMemo should not have any side effects.

const memoVal= useMemo(() => anotherFun(x,y), [x,y]);

useMemo is generally consider a useful hook to use on expensive calculations to prevent unrequired rerenders, although React may also recalculate this more often than you would expect dependant upon many underlying factors.

Redux Hooks

I still think in many ways the two Redux useSelector and useDispatch have really been huge game changers in the way we write and inject properties into components and actually allows us to totally drop the connect from Redux that use to get so in the way of clean nice looking components.

const ConnectedComponent = () => {
	const dispatch = useDispatch();
    const itemState = useSelector(state => state.item);
    
    useEffect(() =>{
    	dispatch(itemAction.fetchItem());
    }, []);
    
    if(itemState.data){
        const item = itemState.data;
    	return (
        	<div>
            <h1>{item.name}</h1>
            </div>    
        )
    }
    
    return (
    	<div>Loading...</div>
    )
}

The above is a very simple example that uses the two most prominate Redux hooks, again Redux have some nice documentation on their hooks, along with zombie chickens...

The useDispatch is used the same way as you would call actions and allows us to just import the raw action and wrap them in this dispatcher which is actually nicer than having to connect them to the component and pass them through a dispatcher object.

The useSelector allows us to pull any state we want from our store and is the prefered method of pulling data out of the store and into our component, it is easier to see what is going on and removed a lot of the cumbersome connect  when we map state to props and actions mapped to the dispatch this means adding in Redux to any component couldn't be easier now!

React Router DOM

The router has quite a few really nice hooks that make it super easy to pull in global data as well which will mean you will no longer have to pass in things like history to the top of the component it can now be mapped via hooks and this is just awesome.

const RoutedComponent = () => {
    const location = useLocation();
    const { id } = useParams();
	const history = useHistory();
    
    return (
    	<React.Fragment>
        	<h1>{`The current route is: ${location.pathname} this pages id is ${id}`}</h1>
		<button onClick={() =>{
			history.push(`${location.pathname}/${+id+1}`);
		}}>next Item</button>
        </React.Fragment>
    )
    
}

So this one has a few different hooks and React Training have a page on the hooks there which is worth a read.

Above we can see the useLocation hook that pretty much just gets the browser location information which most importantly we have pathname which is quite useful for mostly nav bars as it allows attributes such as current page to be set easily or if you want to build a route from the current path it can also work well for that as I do above as well.

The useParams hook allows us to easily pull out the param passed to the page in the format of /page/:id where id in this case is the param, it is however parsed as a string so we can either parseInt or do the JavaScript trick of adding a plus sign before it as in +id to convert to a number.

Lastly the useHistory hook is one of the more useful as it allows us to push new router states allowing the programmatic movement of the page and now it can easily be used via the hook instead of pulling it in as a HOC for the component.

Closing

This covers the main hooks that have been introduced and to be honest they are really great as they create smaller components that feel more self contained and no longer have so many additional props being passed around. I also expect this method of writing components will encourage less passing down of values and this will help greatly in keeping the properties sent between components much more lean and in quite a few cases entirly self contained as I have found that I have written many function components that don't even have any props coming in when using Redux now which is pretty great actually as it makes them much easier to plug and play.

I expect hooks will grow and change over time, I think it is pretty great how much they are currently doing but I expect other libraries will get more hook heavy as well considering they really aren't going anywhere anytime soon and although scary to start with once you start to use them seriously it is hard to go back to the old lifecycle and connect methods we used in 2018.

Photo by Laura Gilchrist on Unsplash