1+ import { useState } from 'react' ;
2+
3+ export default function IPLookup ( ) {
4+ const [ ipAddress , setIpAddress ] = useState ( '' ) ;
5+ const [ result , setResult ] = useState ( null ) ;
6+ const [ loading , setLoading ] = useState ( false ) ;
7+
8+ const lookupIP = async ( ip ) => {
9+ setLoading ( true ) ;
10+ try {
11+ // Using ipapi.co - free, no API key
12+ const url = ip
13+ ? `https://ipapi.co/${ ip } /json/`
14+ : 'https://ipapi.co/json/' ;
15+
16+ const response = await fetch ( url ) ;
17+ const data = await response . json ( ) ;
18+
19+ setResult ( data ) ;
20+ } catch ( error ) {
21+ console . error ( 'Error:' , error ) ;
22+ setResult ( { error : 'Failed to lookup IP' } ) ;
23+ }
24+ setLoading ( false ) ;
25+ } ;
26+
27+ const getMyIP = ( ) => {
28+ setIpAddress ( '' ) ;
29+ lookupIP ( '' ) ;
30+ } ;
31+
32+ return (
33+ < div className = "p-6" >
34+ < h1 className = "text-2xl font-bold mb-4" > IP Address Lookup</ h1 >
35+
36+ < div className = "flex gap-2 mb-4" >
37+ < input
38+ type = "text"
39+ placeholder = "Enter IP address (e.g., 8.8.8.8)"
40+ value = { ipAddress }
41+ onChange = { ( e ) => setIpAddress ( e . target . value ) }
42+ className = "flex-1 px-4 py-2 border rounded"
43+ />
44+ < button
45+ onClick = { ( ) => lookupIP ( ipAddress ) }
46+ disabled = { loading }
47+ className = "px-6 py-2 bg-blue-500 text-white rounded"
48+ >
49+ Lookup
50+ </ button >
51+ < button
52+ onClick = { getMyIP }
53+ disabled = { loading }
54+ className = "px-6 py-2 bg-green-500 text-white rounded"
55+ >
56+ My IP
57+ </ button >
58+ </ div >
59+
60+ { loading && < p > Loading...</ p > }
61+
62+ { result && ! result . error && (
63+ < div className = "bg-gray-100 p-4 rounded" >
64+ < p > < strong > IP:</ strong > { result . ip } </ p >
65+ < p > < strong > City:</ strong > { result . city } </ p >
66+ < p > < strong > Region:</ strong > { result . region } </ p >
67+ < p > < strong > Country:</ strong > { result . country_name } </ p >
68+ < p > < strong > Timezone:</ strong > { result . timezone } </ p >
69+ < p > < strong > ISP:</ strong > { result . org } </ p >
70+ < p > < strong > Latitude:</ strong > { result . latitude } </ p >
71+ < p > < strong > Longitude:</ strong > { result . longitude } </ p >
72+ </ div >
73+ ) }
74+
75+ { result ?. error && (
76+ < p className = "text-red-500" > { result . error } </ p >
77+ ) }
78+ </ div >
79+ ) ;
80+ }
0 commit comments