Real-Time React Analog Clock

Introduction

React can be used directly in HTML, even though JSX does not seem to be supported.

In this blog post, I would like to quickly show how to use React to request time and render time as an analog SVG figure for different time zones.

World Time

The local time, Los Angeles time, New York time, Beijing time, London time, and Tokyo time are displayed in real-time.

React-HTML Implementation

This React-HTML implementation does not use JSX, i.e., all the React components were created using React.createElement. It requests UTC time from worldtimeapi.org once every one second and falls back to local time if the request failed. The UTC time will be converted to the local time in different time zones and the local time will be rendered as a SVG figure.

react_analog_clock.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Hello HTML-React Analog Clock!</title>
</head>
<body>
<div id="root"></div>

<script src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<script>
// Create a React component called Clock that displays the current time in a SVG analog clock.
// The analog clock should have three hands: hour, minute, and second.
// The analog clock should also have 1, 2, 3, ..., 12 numbers around the clock face.
// The analog clock should also have tick marks.
function Clock({ time }) {
const hour = time.getHours();
const minute = time.getMinutes();
const second = time.getSeconds();

const hourAngle = (hour % 12) * 30 + minute * 0.5;
const minuteAngle = minute * 6;
const secondAngle = second * 6;

const hourHand = React.createElement("line", {
x1: "50",
y1: "50",
x2: "50",
y2: "20",
style: {
transform: `rotate(${hourAngle}deg)`,
transformOrigin: "center",
stroke: "black",
strokeWidth: "3",
},
});

const minuteHand = React.createElement("line", {
x1: "50",
y1: "50",
x2: "50",
y2: "10",
style: {
transform: `rotate(${minuteAngle}deg)`,
transformOrigin: "center",
stroke: "black",
strokeWidth: "2",
},
});

const secondHand = React.createElement("line", {
x1: "50",
y1: "50",
x2: "50",
y2: "10",
style: {
transform: `rotate(${secondAngle}deg)`,
transformOrigin: "center",
stroke: "red",
strokeWidth: "1",
},
});

const clockFace = React.createElement("circle", {
cx: "50",
cy: "50",
r: "40",
style: {
fill: "white",
stroke: "black",
strokeWidth: "2",
},
});

const clockNumbers = [];
for (let i = 1; i <= 12; i++) {
const angle = i * 30;
const x = 50 + 35 * Math.sin((angle * Math.PI) / 180);
const y = 50 - 35 * Math.cos((angle * Math.PI) / 180);
clockNumbers.push(
React.createElement(
"text",
{
key: `number-${i}`,
x: x,
y: y,
style: {
textAnchor: "middle",
dominantBaseline: "central",
fontSize: "8px",
},
},
`${i}`
)
);
}

const clock = React.createElement(
"svg",
{
width: "250",
height: "250",
viewBox: "0 0 100 100",
style: {
// border: "1px solid black",
},
},
clockFace,
clockNumbers,
hourHand,
minuteHand,
secondHand
);

// Wrap the clock in a div element and center it.
return React.createElement(
"div",
{
style: {
display: "flex",
justifyContent: "center",
alignItems: "center",
},
},
clock
);
}

function App() {
const [datetime, setDateTime] = React.useState(new Date());

const cityTimeZones = [
{ name: "Los Angeles", timezone: "America/Los_Angeles" },
{ name: "New York", timezone: "America/New_York" },
{ name: "Beijing", timezone: "Asia/Shanghai" },
{ name: "London", timezone: "Europe/London" },
{ name: "Tokyo", timezone: "Asia/Tokyo" },
// Add more cities and timezones as needed
];

function getTime(date, timeZone) {
const time = date.toLocaleTimeString("en-US", {
timeZone: timeZone,
year: "numeric",
month: "2-digit",
day: "2-digit",
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
hour12: false,
});
return time;
}

async function fetchTime() {
try {
// Fetch the current time from worldtimeapi.org.
const response = await fetch("https://worldtimeapi.org/api/ip");
const data = await response.json();
const utc_datetime = new Date(data.utc_datetime);
setDateTime(utc_datetime);
} catch (error) {
// Get local datetime if worldtimeapi.org is down.
setDateTime(new Date());
console.log(error);
}
}

// Asynchronously update the time roughly every 1000 ms.
React.useEffect(function () {
const intervalId = setInterval(function () {
fetchTime();
}, 1000);
return () => clearInterval(intervalId);
}, []);

const timeComponents = cityTimeZones.map(
({ name, timezone }, index) => {
const localTime = getTime(datetime, timezone);
const localDateTime = new Date(localTime);
return React.createElement(
"div",
{ key: `zone-${index}` },
React.createElement("h3", null, `${name}: ${localTime}`),
React.createElement(Clock, { time: localDateTime }),
React.createElement("p", null, "")
);
}
);

return React.createElement(
"div",
null,
React.createElement(
"h3",
null,
`Local: ${getTime(
datetime,
Intl.DateTimeFormat().resolvedOptions().timeZone
)}`
),
React.createElement(Clock, { time: datetime }),
React.createElement("p", null, ""),
React.createElement("div", null, timeComponents)
);
}
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(React.createElement(App));
</script>
</body>
</html>
Author

Lei Mao

Posted on

09-11-2023

Updated on

10-09-2023

Licensed under


Comments