Get a free advice now!

    Pick the topic

    Developer OutsourcingWeb developingApp developingDigital MarketingeCommerce systemseEntertainment systems

    Thank you for your message. It has been sent.

    Tags

    Fetch user IP with fallback in React

    Fetch user IP with fallback in React

    To fetch user IP in React we need to connect to external service providers that will return a proper value. In the case when the first server is not responding, we’ve prepared fallback that will try to connect to a different server. That way we are ready for a situation when one of the servers has downtime.

    Get user info

    The GetUserInfo component will connect to https://ipv4.icanhazip.com to get the IP address. If the connection fails or the response is slower than 5 seconds, we will connect service 2: https://api.ipify.org .

    There is also a waitTime prop that can be used to delay the initial connection.

    public ip address on the localhost

    The Main React component source code:

    // App.tsx
    import React, { useEffect, useState } from "react";
    import './App.css';
    import publicIp from './publicIp.js';
    const GetUserInfo = (props: any) => {
      const {waitTime} = props;
      const [userIpAddress, setUserIpAddress] = useState('');
        const divStyle = {
            fontSize: '2rem',
            textAlign: 'center' as const,
            padding: 20,
            border: '1px solid red',
            maxWidth: 400,
            margin: '20px auto'
        };
      useEffect(() => {
        if (!userIpAddress) {
            setTimeout(function(){
                getIp();
            }, 1000 * waitTime)
        }
      });
      const getIp = () => {
        publicIp.v4()
            .then(
                (result) => {
                  if(result){
                    setUserIpAddress(result);
                  }
                },
                (error) => {
                  console.log(error);
                  setUserIpAddress('0.0.0.0');
                }
            );
      }
      return (
          <div style={divStyle}>
              Your public IP address:
              {!userIpAddress ? ' loading...': ' '}
              {userIpAddress}
          </div>
      );
    }
    function App() {
      return (
        <div className="App">
            <GetUserInfo waitTime={3} />
        </div>
      );
    }
    export default App;
    

    Get user public IP in React

    Thanks to Sindre Sorhus whose Node package ( https://github.com/sindresorhus/public-ip ) was the inspiration for this article. Using this npm package in React is not always possible (issues with the Babel compilation). Therefore, we’ve created standalone: publicIp.js that can be easily used in any React application.

    // https://github.com/sindresorhus/public-ip/blob/main/browser.js
    // publicIp.js
    import ipRegex from 'ip-regex';
    export class CancelError extends Error {
        constructor() {
            super('Request was cancelled');
            this.name = 'CancelError';
        }
        get isCanceled() {
            return true;
        }
    }
    export class IpNotFoundError extends Error {
        constructor(options) {
            super('Could not get the public IP address', options);
            this.name = 'IpNotFoundError';
        }
    }
    const defaults = {
        timeout: 5000,
    };
    const urls = {
        v4: [
            'https://ipv4.icanhazip.com/',
            'https://api.ipify.org/',
        ],
        v6: [
            'https://ipv6.icanhazip.com/',
            'https://api6.ipify.org/',
        ],
    };
    const sendXhr = (url, options, version) => {
        function isIP(string, version = 'v4') {
            if(version === 'v4'){
                return ipRegex.v4({exact: true}).test(string);
            }
            if(version === 'v6'){
                return ipRegex.v6({exact: true}).test(string);
            }
            return ipRegex({exact: true}).test(string);
        }
        const xhr = new XMLHttpRequest();
        let _reject;
        const promise = new Promise((resolve, reject) => {
            _reject = reject;
            xhr.addEventListener('error', reject, {once: true});
            xhr.addEventListener('timeout', reject, {once: true});
            xhr.addEventListener('load', () => {
                const ip = xhr.responseText.trim();
                if (!ip || !isIP(ip, version)) {
                    reject();
                    return;
                }
                resolve(ip);
            }, {once: true});
            xhr.open('GET', url);
            xhr.timeout = options.timeout;
            xhr.send();
        });
        promise.cancel = () => {
            xhr.abort();
            _reject(new CancelError());
        };
        return promise;
    };
    const queryHttps = (version, options) => {
        let request;
        const promise = (async function () {
            const urls_ = [
                ...urls[version],
                ...(options.fallbackUrls ?? []),
            ];
            let lastError;
            for (const url of urls_) {
                try {
                    request = sendXhr(url, options, version);
                    // eslint-disable-next-line no-await-in-loop
                    const ip = await request;
                    return ip;
                } catch (error) {
                    lastError = error;
                    if (error instanceof CancelError) {
                        throw error;
                    }
                }
            }
            throw new IpNotFoundError({cause: lastError});
        })();
        promise.cancel = () => {
            request.cancel();
        };
        return promise;
    };
    const publicIp = {};
    publicIp.v4 = options => queryHttps('v4', {...defaults, ...options});
    publicIp.v6 = options => queryHttps('v6', {...defaults, ...options});
    export default publicIp;
    

    Run application

    The last step is to add the ip-regex dependency to validate if fetched response is valid.

    npm install ip-regex

    Now you can start the application:

    npm start

    Additional note:

    The example application was created using create-react-app:

    npx create-react-app my-app --template typescript

    That’s it for today’s tutorial. Be sure to follow us for other useful tips and guidelines – sign up for our newsletter to stay up to date.

    Comments
    0 response

    Add comment

    Your email address will not be published. Required fields are marked *

    Popular news

    A game changer for WooCommerce users
    • Our Highlights

    A game changer for WooCommerce users

    March 24, 2023 by createIT
    The differences between a web app and a mobile app
    • Services
    • Technology
    • Trends

    The differences between a web app and a mobile app

    March 7, 2023 by createIT
    Webrooming and showrooming
    • Trends

    Webrooming and showrooming

    February 14, 2023 by createIT
    PHPStorm – fix long load time of a directory window
    • Dev Tips and Tricks

    PHPStorm – fix long load time of a directory window

    January 20, 2023 by createIT
    reCAPTCHA v3 – WordPress implementation
    • Dev Tips and Tricks

    reCAPTCHA v3 – WordPress implementation

    January 20, 2023 by createIT
    How to compare GIT and server files
    • Dev Tips and Tricks

    How to compare GIT and server files

    January 19, 2023 by createIT
    How to trigger a click event inside iframe?
    • Dev Tips and Tricks

    How to trigger a click event inside iframe?

    January 19, 2023 by createIT
    FOOEvents – generate a custom CSV report
    • Dev Tips and Tricks

    FOOEvents – generate a custom CSV report

    January 19, 2023 by createIT
    Headless chrome – testing webgl using playwright
    • Dev Tips and Tricks

    Headless chrome – testing webgl using playwright

    January 18, 2023 by createIT
    Preview big SQL files with PilotEdit
    • Dev Tips and Tricks

    Preview big SQL files with PilotEdit

    January 18, 2023 by createIT

    Support – Tips and Tricks
    All tips in one place, and the database keeps growing. Stay up to date and optimize your work!

    Contact us