DEV Community

Cover image for Writing Responsive Components in React
Chukwunazaekpere
Chukwunazaekpere

Posted on • Updated on

Writing Responsive Components in React

In this post, we'll get to understand the implementation of certain hooks in react and as well, making a custom-hook. The hooks of concern in this post are; "useEffect", "useRef" and "useState". I'll then illustrate, how these hooks can be unified into making a custom hook, for making components responsive. It should be understood that hooks can only be used in functional components.
Secondly, the name of any react-hook is descriptive; just by "syllabilising" the word into two;
use: which symbolises that the function is a hook and the other half, e.g Effect, State, Ref, Memo etc, indicates exactly the action which the hook in question carries out.
Thirdly, hooks got their rules. Therefore, it is important to first understand these rules, as they apply to all hooks, irrespective of the use-case(s).
Let's get on then, by understanding what the aforementioned hooks do and their place(s) of use.
Effect (useEffect): as the name indicates, this hook is basically used to implement an effect: re-rendering of the component, w.r.t the alteration observed in the variable(s) in the dependency array. This implies that; if you'd like for instance, your component to be aware that a new user just registered, so you could render this new user, then there must be a variable, either unique to the component or in the global state (context-API or Redux) that is made aware of this event and hence is kept in dependency array, to trigger a re-render of the component. The general form of usage is like so;

    useEffect(() => {
      //....call an API or something else
    }, [variable] // the dependency array); 
Enter fullscreen mode Exit fullscreen mode

State (useState): regulates the state of a variable in a functional component. Say for instance, I'd like to submit a signup form. Then, I could do the below;

interface SignupDataInterface {
    firstname: string,
    lastname: string,
    email: string,
    phone: string,
    password: string,
}

   const [signupData, setSignupData] = useState<SignupDataInterface>({
                                          "firstname": "",
                                          "lastname": "",
                                           "email": "",
                                           "phone": "",
                                           "password": "",
                                           })
Enter fullscreen mode Exit fullscreen mode

The useState hook uses an array "destructuring" feature to provide the variable; signupData and a method to alter the value(s) of this variable. You shouldn't alter the variable-values through any means; but by the use of the method, provided by useState.
Ref (useRef): say you would like to keep the value of a variable after a re-render, the useRef is mostly used for this purpose i.e keeping track of the previous value of a variable. It is used like so;

const initialScreenWidth = useRef(window.innerWidth).current;
Enter fullscreen mode Exit fullscreen mode

The above variable holds the initial screen width of a device irrespective of a re-render. Other use case for the useRef-hook exists. Just do the findings!.
Now, lets create our custom-hook. The reason for this is to implement responsiveness. It then implies that we would want our application to be aware of the devices' dimensions in real time.
Let's write this hook; I called it useWindowDimension (note the first word; "use"):

import { useEffect, useState, useRef } from "react";

interface DimensionInterface {
    width: string | number,
    height: string | number
};

const useWindowDimension = () => {
    // First get the devices dimensions as default value.
    const currentWidth = useRef(window.innerWidth).current;
    const currentHeight = useRef(window.innerHeight).current;

    // This is the effective way of doing it, as opposed to     setting a random value which definitely, isn't true for all devices.
    const [windowDimension, setWindowDimension] = useState<DimensionInterface>({
        width: currentWidth,
        height: currentHeight
    });

// As the devices dimensions change at any time, get the current dimension and set the new dimension as the prevai
    const getDimension = () => {        
        setWindowDimension({
            width: window.innerWidth,
            height: window.innerHeight
        });
    };
    useEffect(() => {
        window.addEventListener("resize", e => getDimension());
        return () => window.removeEventListener("resize", e => getDimension());
    }, []);

    return windowDimension;
};


export default useWindowDimension;
Enter fullscreen mode Exit fullscreen mode

Now, say we would like our p-tags to show headers sizes at varying width, we'd write a component for P-tags;

import React, {HTMLProps} from 'react'
import useWindowDimension from "../../helpers/useWindowDimension";

interface Props extends HTMLProps<any> {

};

const ParagraphHeaderComponent = (props: Props) => {
    const { width } = useWindowDimension();

    return (
        <p style={{display: "flex", width: "100%", justifyContent: "center", alignItems: "center", fontSize: width > 500 ? "27px" : "23px", fontFamily: "serif"}}>
            {props.children}
        </p>
    );
};


export default ParagraphHeaderComponent;
Enter fullscreen mode Exit fullscreen mode

With this, whenever we're on mobile devices, our application is aware and certainly adjusts the header size.
We could as well hide a sidebar component with this or navbar-links, whilst exposing the hamburger button etc.

Discussion (1)