Posted on Leave a comment

The Hidden React Pattern No One Talks About Why Micro Interactions Boost UI Trust Instantly

by Vincy. Last modified on December 16th, 2025.

Developers uses most of the React patterns without even thinking of the patterns greatness in creating user interfaces. We are going to see some of those patterns no one talks about, but uses unintentionally, that boost the UI trust.

When using them, the developers put no intentional effort to uplift the UI trust. But it happens. Those are micro interactions that help for detailing the UI by sending feedback based on user actions. These hidden micro interactions make the UI rich, intuitive and improve the user experience.

A simple React-State-driven micro interaction

This tiny React example manages a button’s press state. It triggers class based on the pressed/released state change of the button element.

//Button press down micro-instruction
const [pressed, setPressed] = useState(false); // button elment to render on the interface
<button
onMouseDown={() => setPressed(true)}
onMouseUp={() => setPressed(false)}
className=className={`
transition-transform duration-150 ${pressed ? "scale-95" : "scale-100"}
`}
>
Save
</button>

This example code 1) allows mouse-down and mouse-up action -> 2) change the 'pressed' state -> 3) triggers class

React Micro Interactions UI Trust

Common React Micro-Interactions that increase user trust

Micro interactions are added in React just like that. These are created by React patterns that are hidden to explain in most of the documentations and tutorials. They are treated as small UX detailing process rather than known as patterns. But, these are greatly contributing in UI enrichment. They helps to improve the UI to make users trust the interface.

The list below show the different micro interaction techniques to send feedback to the UI.

  1. Press down micro interaction when clicking a button.
  2. Dynamic validation on input.
  3. On hovering micro interaction to change the background or add shadow.
  4. Showing spinner on processing background job.
  5. Shaking animation for Reacting to errors.

Press down/up Effect

This Pressable React wrapper is about to have a child clickable element. It consistantly perform the following micro interaction loop for user action.

  • It captures user’s click.
  • Acknowledge by calling on-press event handler.
  • Then send feedback by enabling the press effect via class.
  • Let the user trust the UI.

This React article has the code for using this Pressable wrapper for a ButtonPending component. That component enables the button ‘disabled’ logic based on the ‘loading’ state. If the ‘loading = true’, it will make the button to caption to show “Subscribing…”.

The complete child component of this Pressable wrapper is clickable. This feature increases the success rate of capturing the user-click.

src/components/Pressable.jsx

export default function Pressable({ children, onPress, className }) { return ( <div className={`pressable ${className || ''}`} onClick={onPress}> {children} </div> );
}

react micro form loader animation

src/components/ButtonPending.jsx

export default function ButtonPending({ loading, children, onClick }) { return ( <button className="button-pending" disabled={loading} onClick={onClick}> <span style={{ flex: 1, textAlign: 'center' }}> {loading ? 'Subscribing...' : children} </span> </button> );
}

Micro interaction feedback with Ripple effect

The Ripple effect create an expanded, faded circular view around the click-point. It strongly acknowledges user-click action using this feedback. User will trust the UI by getting this instant visual confirmation.

The click co-ordinates are captured by getBoundingClientRect() to create the absolute positioning of the Ripple.

This component has the reference for the the click target by using React useRef. When the user click on the containerRef, an active ripple instance is created and disappears.

src/components/Ripple.jsx

import { useState, useRef } from 'react'; export default function Ripple({ children }) { const [ripples, setRipples] = useState([]); const containerRef = useRef(null); const addRipple = (e) => { const rect = containerRef.current?.getBoundingClientRect(); if (!rect) return; const size = Math.max(rect.width, rect.height); const x = e.clientX - rect.left - size / 2; const y = e.clientY - rect.top - size / 2; const ripple = { id: Math.random(), x, y, size }; setRipples((prev) => [...prev, ripple]); setTimeout(() => setRipples((prev) => prev.filter((r) => r.id !== ripple.id)), 650); }; return ( <div className="ripple-container" ref={containerRef} onMouseDown={addRipple}> {ripples.map((r) => ( <div key={r.id} className="ripple" style={{ left: r.x, top: r.y, width: r.size, height: r.size }} /> ))} {children} </div> );
}

Dynamic validation shows error on form section

Form validation is called at the moment when users giving input. It will send feedback by showing validation error immediately. This will build trust by showing instant feedback.

react micro interaction validation error

This React FormSection component has the reference for all the React state variables needed for enabling this micro interaction concept.

This section accepts form data and call a field level validation on typing the input. This example validates the Name and Email fields. Once the user enters wrong data or giving input in wrong format, then the field level validation error will be managed in the fieldErrors.

The field onchange handler update only the current field data with the formData state then calls the field specific validation.

src/components/FormSection.jsx

export default function FormSection({ formData, fieldErrors, loading, setFormData, validateField, setError }) { return ( <> <div className="form-group"> <label>Full Name</label> <input type="text" placeholder="John Doe" value={formData.name} onChange={(e) => { const val = e.target.value; setFormData({ ...formData, name: val }); validateField("name", val); setError(false); }} disabled={loading} /> {fieldErrors.name && <p className="field-error">{fieldErrors.name}</p>} </div> <div className="form-group"> <label>Email Address</label> <input type="email" placeholder="john@example.com" value={formData.email} onChange={(e) => { const val = e.target.value; setFormData({ ...formData, email: val }); validateField("email", val); setError(false); }} disabled={loading} /> {fieldErrors.email && <p className="field-error">{fieldErrors.email}</p>} </div> </> );
}

React micro interaction on hover

On hovering an element, the animation effect can be given in different ways. The HoverLift and HoverApplyBorder wrapper helpers are most frequently used micro interaction techniques.

These functions encloses hovered target with the lift effect or border.

src/components/HoverLift.jsx

export default function HoverLift({ children }) { return <div className="hover-lift">{children}</div>;
}

react micro button hover border

src/components/HoverApplyBorder.jsx

export default function HoverApplyBorder({ children }) { return ( <div className="hover-border"> {children} </div> );
}

Micro interaction pattern used during progressing user request

When submitting a form, the user request is taken to the backend and the process will be going on. During the processing time, the useDelayedLoader will be shown to the form near the button. Also, the FadePresence wrapper is applied to the form component to dim the UI. It lets the user know that the form-action request is taken for processing. It will build trust about the user interface.

src/components/useDelayedLoader.js

import { useState, useEffect } from 'react';
export default function useDelayedLoader(isLoading, delay = 450) { const [showLoader, setShowLoader] = useState(false); useEffect(() => { let timer; if (isLoading) { timer = setTimeout(() => setShowLoader(true), delay); } else { // defer state update to next tick to avoid ESLint warning timer = setTimeout(() => setShowLoader(false), 0); } return () => clearTimeout(timer); }, [isLoading, delay]); return showLoader;
}

src/components/FadePresence.jsx

export default function FadePresence({ show, children }) { return ( <div className="fade-presence" style={{ opacity: show ? 1 : 0.5, transform: show ? 'translateY(0)' : 'translateY(10px)', pointerEvents: show ? 'auto' : 'none', }} > {children} </div> );
}

Show response or progressing state of the form submission

src/components/StatusSection.jsx

export default function StatusSection({ loading, showLoader, success, error }) { return ( <div className="status-box"> {showLoader && loading && ( <div className="loader"> <div className="loader-spinner" /> <span>Subscribing...</span> </div> )} {!loading && success && ( <div className="success"> <span className="success-icon">✓</span> <p>Check your email to confirm</p> </div> )} {!loading && error && ( <div className="error-box"> <span className="error-icon">!</span> <p>Please fill all fields</p> </div> )} </div> );
}

Send feedback effect on success or failure

react micro form validation error

src/components/ShakeOnError.jsx

export default function ShakeOnError({ isError, children }) { return <div className={isError ? 'shake' : ''}>{children}</div>;
}

react micro form validation success

src/components/PulseOnSuccess.jsx

export default function PulseOnSuccess({ success, children }) { return <div className={success ? 'pulse' : ''}>{children}</div>;
}

Button controls that triggers React micro interaction loop

Most of the micro interactions are added to the “Subscribe Now” button. Added to that, an additional button interfaces are provided in the code to have a quick experiment with the effects.

These controls will show you the hover lift effect and update the status section without completing the form.

react micro interactions controls

src/components/ControlsSection.jsx

import HoverApplyBorder from "./HoverApplyBorder";
import Ripple from "./Ripple";
export default function ControlsSection({ setError, setSuccess, setLoading, setFormData, setFieldErrors }) { return ( <div className="controls"> <h3 className="controls-title">Controls</h3> <div className="button-grid"> <HoverApplyBorder> <Ripple> <button className="control-btn reset" onClick={() => { setError(false); setSuccess(false); setLoading(false); setFormData({ email: "", name: "" }); setFieldErrors({ name: "", email: "" }); }}> Reset All </button> </Ripple> </HoverApplyBorder> <HoverApplyBorder> <button className="control-btn error" onClick={() => { setError(false); setTimeout(() => setError(true), 50); setSuccess(false); setLoading(false); }}> Trigger Error </button> </HoverApplyBorder> <HoverApplyBorder> <button className="control-btn success" onClick={() => { setSuccess(false); setTimeout(() => setSuccess(true), 50); setError(false); setLoading(false); }} > Trigger Success </button> </HoverApplyBorder> <HoverApplyBorder> <button className="control-btn loading" onClick={() => { setLoading(true); setTimeout(() => setLoading(false), 2000); }} > Trigger Loading </button> </HoverApplyBorder> </div> </div> );
}

React frontend form uses micro interaction techniques

This is the landing page JSX that uses all the components and wrapper classes we have seen above. This script will be useful how the micro interaction wrapper are used in the React frontend components.

src/App.jsx

import { useState } from "react";
import Pressable from "./components/Pressable";
import ShakeOnError from "./components/ShakeOnError";
import FadePresence from "./components/FadePresence";
import PulseOnSuccess from "./components/PulseOnSuccess";
import HoverLift from "./components/HoverLift";
import ButtonPending from "./components/ButtonPending";
import useDelayedLoader from "./components/useDelayedLoader"; import FormSection from "./components/FormSection";
import StatusSection from "./components/StatusSection";
import ControlsSection from "./components/ControlsSection"; export default function App() { const [loading, setLoading] = useState(false); const [error, setError] = useState(false); const [success, setSuccess] = useState(false); const [formData, setFormData] = useState({ email: "", name: "" }); const [fieldErrors, setFieldErrors] = useState({ name: "", email: "" }); const showLoader = useDelayedLoader(loading, 450); const handleSubmit = () => { setSuccess(false); setError(false); const isNameEmpty = !formData.name.trim(); const isEmailEmpty = !formData.email.trim(); if (isNameEmpty || isEmailEmpty) { setTimeout(() => setError(true), 20); return; } if (validateField("name", formData.name, true) || validateField("email", formData.email, true)) { return; } setLoading(true); setTimeout(() => { setLoading(false); setSuccess(true); setTimeout(() => { setFormData({ email: "", name: "" }); setFieldErrors({ name: "", email: "" }); }, 1500); }, 1300); }; const validateField = (field, value, returnOnly = false) => { let message = ""; if (field === "name") { if (!value.trim()) message = "Name is required"; else if (value.trim().length < 4) message = "Name must be at least 4 characters"; } if (field === "email") { const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; if (!value.trim()) message = "Email is required"; else if (!emailRegex.test(value)) message = "Invalid email format"; } if (!returnOnly) { setFieldErrors((prev) => ({ ...prev, [field]: message })); } return message; }; return ( <div className="container"> <main> <ShakeOnError isError={error}> <PulseOnSuccess success={success}> <div className="card"> <header> <h1>✉ Newsletter Signup</h1> <p className="subtitle">Subscribe to get exclusive updates</p> </header> <FadePresence show={!loading}> <FormSection formData={formData} fieldErrors={fieldErrors} loading={loading} setFormData={setFormData} validateField={validateField} setError={setError}/> </FadePresence> <div className="action-row"> <HoverLift> <Pressable onPress={handleSubmit}> <ButtonPending loading={loading}>Subscribe Now</ButtonPending> </Pressable> </HoverLift> <StatusSection loading={loading} showLoader={showLoader} success={success} error={error} /> </div> <div className="divider"></div> <ControlsSection setError={setError} setSuccess={setSuccess} setLoading={setLoading} setFormData={setFormData} setFieldErrors={setFieldErrors} /> <footer>Stay updated! Subscribe to get the latest news directly in your inbox.</footer> </div> </PulseOnSuccess> </ShakeOnError> </main> </div> );
}

Output:

react micro interaction validation effects

Some of the libraries to build micro-interaction and animation in React

These are some of the useful libraries that ease the process of building React app with micro-interaction techniques and smooth animation effects.

  • Framer Motion – It is suitable to use for its perfect result for on hover or on Press effects, enter or exit transition, layout shift micro-interactions.
  • React Spring – It is known for its smooth drag and drop, expand-collapse, and toggle effects.
  • AutoAnimate – It is popularly known for its auto DOM changes with minimal config.
  • GSAP – GreenSock animation is recommended for an embedding platform for imposing complex animation on the frontend. The example for the complex animations are, chained effects, SVG morphing and more.

Conclusion

We have seen how do micro-interactions increase UI trust. An interactive and intuitive web interface impresses endusers and encourages them to use it. React web app using micro interaction patterns earns user trust by sending appropriate feedback to the interface.

The feedbacks close the loop to let the users understand that their actions are taken for processing. Various kind of feedbacks are used to acknowledge the users. These are the commonly used techniques in gain the user’s trust.

  • Displaying feedback messages.
  • Animation effects like shaking login when entering wrong credentials.
  • Animated icons to show tick on successful payment transactions.

We see some of the micro interaction techniques to show status, progress bar, or to shake UI if something went wrong.

References:

  1. Power of response time and its limits in UI/UX.
  2. Role of micro interaction in modern UI.

Download

Vincy
Written by Vincy, a web developer with 15+ years of experience and a Masters degree in Computer Science. She specializes in building modern, lightweight websites using PHP, JavaScript, React, and related technologies. Phppot helps you in mastering web development through over a decade of publishing quality tutorials.

↑ Back to Top

Posted on Leave a comment

React Charts and Graphs with Recharts: Visualize Data Beautifully

by Vincy. Last modified on December 3rd, 2025.

Representing data in a chart view is a huge subject in Mathematics and Computer Science. If you have the skill to transform raw numbers into a chart view, it’s a brilliant representation that makes users understand any complex data quickly.

Learning to build a chart in React will elevate your UI and make your application feel truly professional.

This React example includes dashboard visualization to display the following chart view.

  1. Sales & revenue trend in the form of line chart.
  2. Product-wise performance using column chart.
  3. Browser distribution in pie chart.
  4. Area chart to visualize users’ active time.

It uses Recharts library to show the raw data in a graph or chart form, as shown below.

React Charts Graphs Recharts Data Visualization

Main React component containing chart components

The DataVisualization component manages React states and useEffect. It manages the separate state variables for each type of charts.

The React useEffect fetches the JSON data and set them to bind for the charts.

The chart UI are created as separate components and used in the dashboard wrapper.

src/components/DataVisualization.jsx

import { useState, useEffect } from "react";
import Header from "../components/Header";
import StatsCards from "../components/StatsCards";
import LineChartBox from "../components/LineChartBox";
import BarChartBox from "../components/BarChartBox";
import PieChartBox from "../components/PieChartBox";
import AreaChartBox from "../components/AreaChartBox";
import Footer from "../components/Footer"; const DataVisualization = () => { const [lineData, setLineData] = useState([]); const [barData, setBarData] = useState([]); const [pieData, setPieData] = useState([]); const [areaData, setAreaData] = useState([]); useEffect(() => { fetch("/data/dashboard.json") .then((res) => res.json()) .then((data) => { setLineData(data.lineData); setBarData(data.barData); setPieData(data.pieData); setAreaData(data.areaData); }) .catch((err) => console.error("Error loading data:", err)); }, []); return ( <div className="dashboard-wrapper"> <div className="dashboard-container"> <Header /> <StatsCards /> <div className="charts-grid"> <LineChartBox data={lineData} /> <BarChartBox data={barData} /> <PieChartBox data={pieData} /> <AreaChartBox data={areaData} /> </div> <Footer /> </div> </div> );
};
export default DataVisualization;

Chart visualization header with trending data cards

In this code, the chart components are created for rendering in a dashboard. Added to the chart representation, the dashboard shows cards to display trending data.

You can replace it with your applications progressive data in this cards. For demonstration purpose, they are all static data from the client-side. It’s a matter of minute to plug your dynamic data from the database.

react chart graph visualization header

src/components/Header.jsx

const Header = () => ( <header className="dashboard-header"> <h1>Data Visualization Dashboard</h1> <p>Beautiful charts and graphs powered by Recharts in React</p> </header>
);
export default Header;

react chart graph statscards

src/components/StatsCards.jsx

import { TrendingUp, BarChart3, Users, Activity } from "lucide-react";
const StatsCards = () => { const stats = [ { icon: <TrendingUp strokeWidth={1} />, label: "Total Sales", value: "$24,850", change: "+12.5%" }, { icon: <BarChart3 strokeWidth={1} />, label: "Revenue", value: "$48,200", change: "+8.2%" }, { icon: <Users strokeWidth={1} />, label: "Users", value: "12,543", change: "+23.1%" }, { icon: <Activity strokeWidth={1} />, label: "Growth", value: "34.8%", change: "+5.4%" }, ]; return ( <div className="stats-grid"> {stats.map((stat, index) => ( <div key={index} className="stat-card"> <div className="stat-top"> <span className="stat-icon">{stat.icon}</span> <span className="stat-change">{stat.change}</span> </div> <p className="stat-label">{stat.label}</p> <p className="stat-value">{stat.value}</p> </div> ))} </div> );
};
export default StatsCards;

Line chart to show the sales revenue graph

This script imports the Recharts component required for rendering a line chart. The following components are mostly required for all the charts.

  • XAxis, YAxis
  • Tooltip and Legend
  • CartisanGrid
  • ResponsiveContainer

The chart is rendered in a ResponsiveContainer block which support chart scaling based on the viewport size. The Tooltip and CartisanGrid will be shown on hovering the chart. The X,Y axis and chart legend are very usual part of the chart view.

The LineChart and Line components are exclusive to this type of chart. It accepts Recharts attributes to set the stroke width and color of the line graph.

react data visualization line chart

src/components/LineChartBox.jsx

import { LineChart, Line, XAxis, YAxis, Tooltip, CartesianGrid, Legend, ResponsiveContainer } from "recharts";
const LineChartBox = ({ data }) => ( <div className="chart-card"> <h2>Sales & Revenue Trend</h2> <ResponsiveContainer width="100%" height={300}> <LineChart data={data}> <CartesianGrid strokeDasharray="3 3" stroke="#475569" /> <XAxis stroke="#94a3b8" /> <YAxis stroke="#94a3b8" /> <Tooltip /> <Legend /> <Line type="monotone" dataKey="sales" stroke="#3b82f6" strokeWidth={1} /> <Line type="monotone" dataKey="revenue" stroke="#10b981" strokeWidth={1} /> </LineChart> </ResponsiveContainer> </div>
);
export default LineChartBox;

Bar chart fir showing performance graph

The BarChart and Bar component of the Recharts library are used in this script. The BarChart accepts chart data and Bar element requires the color specification to fill the column bar.

src/components/BarChartBox.jsx

import { BarChart, Bar, XAxis, YAxis, Tooltip, CartesianGrid, ResponsiveContainer } from "recharts";
const BarChartBox = ({ data }) => ( <div className="chart-card"> <h2>Product Performance</h2> <ResponsiveContainer width="100%" height={300}> <BarChart data={data}> <CartesianGrid strokeDasharray="3 3" stroke="#475569" /> <XAxis dataKey="category" stroke="#94a3b8" /> <YAxis stroke="#94a3b8" /> <Tooltip /> <Bar dataKey="value" fill="#8b5cf6" /> </BarChart> </ResponsiveContainer> </div>
);
export default BarChartBox;

Pie chart – Recharts – showing browser distribution

This Recharts component accepts the inner-radius, outer-radius, cy, cx properties to draw the pie chart.

This chart type will have a Pie component which is to draw the pie wedges in the wrapper. The Cell is to draw each pie slices.

It receives the data and datakey in the <Pie /> component of this Recharts library.

react data visualization pie chart

src/components/PieChartBox.jsx

import { PieChart, Pie, Tooltip, ResponsiveContainer, Cell } from "recharts";
const PieChartBox = ({ data }) => ( <div className="chart-card"> <h2>Browser Distribution</h2> <ResponsiveContainer width="100%" height={300}> <PieChart> <Pie data={data} dataKey="value" innerRadius={60} outerRadius={100} paddingAngle={2} cx="50%" cy="50%" > {data.map((entry, i) => ( <Cell key={i} fill={entry.color} /> ))} </Pie> <Tooltip /> </PieChart> </ResponsiveContainer> <div className="pie-legend"> {data.map((item, i) => ( <div key={i} className="legend-item"> <span className="legend-color" style={{ background: item.color }} /> <span>{item.name}: {item.value}%</span> </div> ))} </div> </div>
);
export default PieChartBox;

Area chart using the Recharts library

In this graph, it shows the active users count by time. It represents how many users are actively using your app at a particular point of time. It will help to monitor the spikes and drop in the traffic, product or services usages and more.

The AreaChart is the wrapper that contains the Area element which is to show the shaded part of the chart as shown below.

The JSON data contains the time and user count for each level of the graph. The area is highlighted within a LinearGadient definition.

react data visualization area chart

src/components/AreaChartBox.jsx

import { AreaChart, Area, XAxis, YAxis, Tooltip, CartesianGrid, ResponsiveContainer } from "recharts";
const AreaChartBox = ({ data }) => ( <div className="chart-card"> <h2>Active Users Over Time</h2> <ResponsiveContainer width="100%" height={300}> <AreaChart data={data}> <defs> <linearGradient id="colorUsers" x1="0" y1="0" x2="0" y2="1"> <stop offset="5%" stopColor="#f59e0b" stopOpacity={0.8} /> <stop offset="95%" stopColor="#f59e0b" stopOpacity={0} /> </linearGradient> </defs> <CartesianGrid strokeDasharray="3 3" stroke="#475569" /> <XAxis dataKey="time" stroke="#94a3b8" /> <YAxis stroke="#94a3b8" /> <Tooltip /> <Area type="monotone" dataKey="users" stroke="#f59e0b" fill="url(#colorUsers)" /> </AreaChart> </ResponsiveContainer> </div>
);
export default AreaChartBox;

react chart graph data visualization

Conclusion

The React charts provide graphical view to understand your trending data. The line chart plots the performance range over time, the pie chart slices down browser distribution at a quick view, and the area chart visualizes the user activity patterns. By using Recharts responsive wrapper, each graph fit for different screen size. Overall, these charts transform raw numbers into visual stories to help efficient decision making.

References:

  1. Recharts library documentation
  2. Best chart libraries for React

Download

Vincy
Written by Vincy, a web developer with 15+ years of experience and a Masters degree in Computer Science. She specializes in building modern, lightweight websites using PHP, JavaScript, React, and related technologies. Phppot helps you in mastering web development through over a decade of publishing quality tutorials.

↑ Back to Top

Posted on Leave a comment

Integrate Google Maps in React for Real-Time Location Tracking

by Vincy. Last modified on November 28th, 2025.

Integrating Google Maps into a React app is a powerful location-based feature. It helps for live user tracking to delivery routes, geo-fencing, and real-time movement progression. It is one of the simplest jobs with the help of the Google Maps JavaScript API and React libraries.

Real-time location tracking improves the usability of your apps. It can be implemented for dashboards, for tracking location on Duty, or anything that involves dynamic location-based requirements.

This React example helps to integrate Google Maps into React. It renders dynamic maps to the UI and displays markers to pinpoint the live location. It continuously updates the user’s position using the browser’s Geolocation API.

React Google Maps Realtime Location Tracking

Google Maps Integration steps

These are the few steps to enable required Google API services and configure the key credentials with the React App. This process builds a channel between the enduser and the Google cloud services for which they are registered with.

google cloud api library services

  1. Login with Google Cloud Console and create a new project.
  2. Choose APIs and Services and enable Maps JavaScript API.
  3. Go to Credentials menu and CREATE CREDENTIALS -> API Key to generate API key.
  4. Install React Google Maps library in your app using npm install @react-google-maps/api.
  5. Configure this key to your React app when loading React Google Maps JS library.

The credentials page shows the list of API keys generated. You can restrict the keys for specific domains or for using particular Google API services.

google cloud api credential

Rendering Google Maps with current location

The TrackLocation JSX shows HTML components for displaying the Google Map and a location search option.

If the location search is not applied, it is showing the marker on the users current location.

react google map landing page

src/components/TrackLocation.jsx

import { useState } from "react";
import SearchBox from "./SearchBox";
import MapContainerComponent from "./MapContainerComponent"; export default function TrackLocation() { const [searchQuery, setSearchQuery] = useState("");
return ( <div style={{ display: "flex" }}> <SearchBox onSearch={setSearchQuery} /> <MapContainerComponent searchQuery={searchQuery} /> </div> );
}

React Google Maps Component

This is the main component which initiates the React Google Maps library by configuring the Google Cloud API service key.

It manages React states for having the Map instance, map marker location and the searched location. The marker location is depends on two factors. It will be changed dynamically to show the real-time location of the user. Also, it is changed when the search is applied.

With the help of the client side Geo location capabilities, navigator.geolocation gets the latitude and longitude of the user’s position. Then it is used to build the location object to plot the marker to the map.

src/components/MapContainerComponent.jsx

import { useEffect, useState } from "react";
import { GoogleMap, useJsApiLoader } from "@react-google-maps/api";
import LocationMarker from "./LocationMarker"; export default function MapContainerComponent({ searchQuery }) { const [map, setMap] = useState(null); const [userLocation, setUserLocation] = useState(null); const [searchLocation, setSearchLocation] = useState(null); const { isLoaded } = useJsApiLoader({ googleMapsApiKey: "YOUR API KEY", libraries: ["places"], }); useEffect(() => { if (navigator.geolocation) { const watchId = navigator.geolocation.watchPosition( (pos) => { const newLoc = { lat: pos.coords.latitude, lng: pos.coords.longitude, }; setUserLocation(newLoc); if (map && !searchLocation) { map.setCenter(newLoc); map.setZoom(13); } }, (err) => console.error("Location error:", err), { enableHighAccuracy: true, maximumAge: 1000 } ); return () => navigator.geolocation.clearWatch(watchId); } else { console.error("Geolocation not supported"); } }, [map, searchLocation]); useEffect(() => { if (!searchQuery || !window.google || !map) return; const geocoder = new window.google.maps.Geocoder(); geocoder.geocode({ address: searchQuery }, (results, status) => { if (status === "OK" && results[0]) { const loc = results[0].geometry.location; const newSearchLoc = { lat: loc.lat(), lng: loc.lng() }; setSearchLocation(newSearchLoc); if (userLocation) { const bounds = new window.google.maps.LatLngBounds(); bounds.extend(userLocation); bounds.extend(newSearchLoc); map.fitBounds(bounds); } else { map.setCenter(newSearchLoc); map.setZoom(12); } } else { console.warn("Location not found for:", searchQuery); } }); }, [searchQuery, map, userLocation]); const zoomToLocation = (loc) => { if (!map || !loc) return; map.panTo(loc); map.setZoom(15); }; return ( <div className="map-container"> {isLoaded && ( <GoogleMap mapContainerStyle={{ width: "100%", height: "100vh" }} center={userLocation || { lat: 20.5937, lng: 78.9629 }} zoom={userLocation ? 13 : 5} onLoad={setMap} options={{ streetViewControl: false, mapTypeControl: false, fullscreenControl: false, }}> <LocationMarker position={userLocation} title="Your Location" onClick={() => zoomToLocation(userLocation)} /> <LocationMarker position={searchLocation} title="Tracked Location" onClick={() => zoomToLocation(searchLocation)} /> </GoogleMap> )} {userLocation && ( <button className="floating-btn" onClick={() => zoomToLocation(userLocation)}> My Location </button> )} </div> );
}

This LocationMarker component is part of the main React component that accepts the users location or searched location. It pins the marker to the Map based on the location details.

src/components/LocationMarker.js

import React from "react";
import { Marker } from "@react-google-maps/api"; export default function LocationMarker({ position, title, onClick }) { return position ? <Marker position={position} title={title} onClick={onClick} /> : null;
}

Google Maps Search feature

The search form contains interface to enter the place to mark on the Map. When the search is applied, the LocationMarker rendered with the position:searchLocation shows the marker on the right place.

src/components/SearchBox.jsx

import { useState } from "react"; export default function SearchBox({ onSearch }) { const [query, setQuery] = useState(""); const handleSubmit = (e) => { e.preventDefault(); if (query.trim()) onSearch(query); }; return ( <div className="search-sidebar"> <h3 className="sidebar-title">Track Location</h3> <form onSubmit={handleSubmit}> <input type="text" placeholder="Enter a place" value={query} onChange={(e) => setQuery(e.target.value)} className="search-input" /> <button type="submit" className="search-btn"> Search </button> </form> </div> );
}

Conclusion

Real-time location tracking in React becomes easy with the joint capabilities of the Geolocation API and Google Maps. It changes the user’s position on movement. This example enriches user experience with a live movement tracking feature. And, it will be easy to use in a location-based React application that needs to render users’ live locations.

References:

  1. React Google Maps API wrapper.
  2. Google Maps rendering best practices.

Download

Vincy
Written by Vincy, a web developer with 15+ years of experience and a Masters degree in Computer Science. She specializes in building modern, lightweight websites using PHP, JavaScript, React, and related technologies. Phppot helps you in mastering web development through over a decade of publishing quality tutorials.

↑ Back to Top

Posted on Leave a comment

How to Build a Responsive React Navbar with Dropdown and Mobile Menu

by Vincy. Last modified on November 25th, 2025.

A responsive navigation bar is a one of a must-needed requirement of any modern web application. It is an easy job if the navigation bar contains single level menu and action controls. But, it will be complex it is a multi-level menu to fit the layout into a small viewport.

With this React example code you’ll learn how to build a responsive React navbar. It includes a multi-level dropdown menu for different view port. It will a plugable and reusable React component for your different application frontend.

Responsive React Navbar Dropdown Mobile Menu

Responsive navbar in React header

This React JSX code has the a responsive navigation bar component. It provides 1) menu bar with Desktop and mobile variants, 2)sub menu bar with click-to-expand effect.

The menuData contains the array of multi-level menu items. The image shown below renders the horizontal menu on the site header.

react drop down navbar

src/components/Navbar/Navbar.jsx

import { useState } from "react";
import menuData from "./MenuData";
import Dropdown from "./DropDown";
import "../../../public/assets/css/style.css"; const Navbar = () => { const [menuOpen, setMenuOpen] = useState(false); const [openIndex, setOpenIndex] = useState(null); const toggleSubmenu = (index, e) => { if (window.innerWidth <= 768) { e.preventDefault(); setOpenIndex(openIndex === index ? null : index); } };
return ( <nav className="navbar"> <div className="navbar-container"> <h2 className="logo"></h2> <button className="menu-toggle" onClick={() => setMenuOpen(!menuOpen)} aria-label="Toggle menu" > ☰ </button> <ul className={`menu ${menuOpen ? "open" : ""}`}> {menuData.map((menu, i) => ( <li key={i} className="menu-item has-submenu"> <a href="#" onClick={(e) => toggleSubmenu(i, e)}> {menu.title} <span className="expand">▼</span> </a> {menu.subMenu && ( <Dropdown items={menu.subMenu} className={openIndex === i ? "open" : ""} /> )} </li> ))} </ul> </div> </nav>
);
};
export default Navbar;

These are the main and submenu items defined for this React example.

src/components/Navbar/MenuData.js

const menuData = [ { title: "Popular Toys", subMenu: [ { title: "Video Games", subMenu: [ { title: "Car", subMenu: ["Racing Car", "Toy Car", "Remote Car"] }, "Bike Race", "Fishing" ] }, "Barbies", "Teddy Bear", "Golf Set" ] }, { title: "Recent Toys", subMenu: [ "Yoyo", "Doctor Kit", { title: "Fun Puzzle", subMenu: ["Cards", "Numbers"] }, "Uno Cards" ] }, { title: "Toys Category", subMenu: [ "Battery Toys", { title: "Remote Toys", subMenu: ["Cars", "Aeroplane", "Helicopter"] }, "Soft Toys", "Magnet Toys" ] }
]; export default menuData;

React menu dropdown hooks to toggle submenu

A component Dropdown returns the submenu look-and-feel. The React state openIndex has the menu open/close state by its index.

The Dropdown component’s expand/collapse state is depends on the menuOpen set with a toggle action. The menu toggle effect is for the mobile view to slide down the menu options on clicking a burger icon.

react drop down navbar menu

src/components/Navbar/DropDown.jsx

import { useState } from "react"; const Dropdown = ({ items, className }) => { const [openIndex, setOpenIndex] = useState(null); const toggleSubmenu = (index, e) => { if (window.innerWidth <= 768) { e.preventDefault(); setOpenIndex(openIndex === index ? null : index); } }; return ( <ul className={`dropdown ${className || ""}`}> {items.map((item, i) => typeof item === "string" ? ( <li key={i}> <a href="#">{item}</a> </li> ) : ( <li key={i} className="has-submenu"> <a href="#" onClick={(e) => toggleSubmenu(i, e)}> {item.title} <span className="expand">›</span> </a> {item.subMenu && ( <Dropdown items={item.subMenu} className={openIndex === i ? "open" : ""} /> )} </li> ) )} </ul> );
};
export default Dropdown;

Mobile menu navbar view

This heading shows the mobile view of this responsive navbar. In the mobile view, a burger icon will be appeared on the top right corner of the web layout.

This icon’s click event is bound to toggle a sliding menu. In this sliding menu, each menu items are vertically expandable to show its submenu.
react drop down navbar mobile responsive

References:

  1. Navigation bar modals with Material Design.
  2. Free navigation bar templates by Figma.

Download

Vincy
Written by Vincy, a web developer with 15+ years of experience and a Masters degree in Computer Science. She specializes in building modern, lightweight websites using PHP, JavaScript, React, and related technologies. Phppot helps you in mastering web development through over a decade of publishing quality tutorials.

↑ Back to Top

Posted on Leave a comment

React File Upload with Preview and Drag-and-Drop Support

by Vincy. Last modified on November 20th, 2025.

This example contains a React drag-and-drop file upload with file type and size validation. It connects backend to upload files to the server via Axios.

The workflow allows users to drop files to upload and shows file preview below the drop area. This file upload example includes the following featured functionalities.

  1. Drag and drop
  2. File validation
  3. Uploading to backend
  4. Saving file path to database
  5. Preview after upload
  6. Error handling

It is easy to integrate into any React application, since it is structured with separate components for the upload and preview UI.

React File Upload Preview Drag Drop

React UI with file upload interface

Two React components created for this file upload UI. Those are UploadBox and FilePreview.

The UploadBox is the drop area for dragged files to be uploaded. Once upload completed, file thumbnails are shown in a preview box by using the FilePreview component.

The FileUpload JSX handles the following processes before uploading a file.

  1. File validation about its extension and size.
  2. Handling errors or success acknowledgement for UI.
  3. Preparing form data with the file binaries.

react file upload empty state

src/components/FileUpload.jsx

import { useState } from "react";
import axios from "axios";
import SERVER_SIDE_API_ROOT from "../../config";
import FilePreview from "./FilePreview";
import UploadBox from "./UploadBox";
import "../../public/assets/css/style.css";
const FileUpload = () => { const [files, setFiles] = useState([]); const [dragActive, setDragActive] = useState(false); const [uploading, setUploading] = useState(false); const [errorMsg, setErrorMsg] = useState(""); const allowedExtensions = ["jpg", "jpeg", "png", "gif", "pdf", "doc", "docx", "txt"]; const MAX_FILE_SIZE = 2 * 1024 * 1024; const uploadFiles = async (fileList) => { setErrorMsg(""); const safeFiles = []; const rejectedFiles = []; fileList.forEach((file) => { const ext = file.name.split(".").pop().toLowerCase(); if (!allowedExtensions.includes(ext)) return rejectedFiles.push("Invalid file type"); if (file.size > MAX_FILE_SIZE) return rejectedFiles.push("Maximum file size is 2MB."); if (file.size <= 0) return rejectedFiles.push("Empty file"); safeFiles.push(file); }); if (rejectedFiles.length > 0) { setErrorMsg(rejectedFiles[0]); setUploading(false); return; } if (!safeFiles.length) return; const formData = new FormData(); safeFiles.forEach((file) => formData.append("files[]", file)); setUploading(true); const delay = new Promise((resolve) => setTimeout(resolve, 800)); try { const res = await Promise.all([ axios.post(`${SERVER_SIDE_API_ROOT}/file-upload.php`, formData, { headers: { "Content-Type": "multipart/form-data" }, }), delay, ]); const uploadedFiles = res[0].data.files.filter((f) => f.status === "uploaded"); setFiles((prev) => [...prev, ...uploadedFiles.map(f => safeFiles.find(sf => sf.name === f.name))]); } catch { setErrorMsg("Server error — please try again later."); } setUploading(false); }; const handleDrop = async (e) => { e.preventDefault(); setDragActive(false); await uploadFiles(Array.from(e.dataTransfer.files)); }; return ( <div className="upload-wrapper"> <UploadBox dragActive={dragActive} uploading={uploading} errorMsg={errorMsg} handleDrop={handleDrop} setDragActive={setDragActive} > </UploadBox> <FilePreview files={files} uploading={uploading} /> </div> );
};
export default FileUpload;

PHP file upload endpoint

The PHP script validates the received file binary before uploading to the server directory. If the validation passes, this script give name to the file with a unique random id.

Once the PHP move_uploaded_file() saves the files to the directory, this code inserts the target path to the database.

drag-drop-file-upload-api/file-upload.php

<?php
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: POST, GET, OPTIONS");
header("Access-Control-Allow-Headers: Content-Type");
include "db.php";
$uploadDir = "uploads/";
$response = [];
if (!file_exists($uploadDir)) { mkdir($uploadDir, 0777, true);
}
$allowedExtensions = ['jpg', 'jpeg', 'png', 'gif', 'pdf', 'txt', 'doc', 'docx'];
$maxFileSize = 2 * 1024 * 1024; foreach ($_FILES['files']['name'] as $key => $name) { $tmpName = $_FILES['files']['tmp_name'][$key]; $extension = strtolower(pathinfo($name, PATHINFO_EXTENSION)); $size = $_FILES['files']['size'][$key]; if (!in_array($extension, $allowedExtensions)) { $response[] = [ "name" => $name, "status" => "blocked", "message" => "File type not allowed (.{$extension})" ]; continue; } if ($size > $maxFileSize) { $response[] = [ "name" => $name, "status" => "blocked", "message" => "Maximum file size is 2M." ]; continue; } if ($size <= 0) { $response[] = [ "name" => $name, "status" => "blocked", "message" => "Empty file" ]; continue; } $uniqueName = uniqid() . "_" . basename($name); $targetPath = $uploadDir . $uniqueName; if (move_uploaded_file($tmpName, $targetPath)) { $stmt = $conn->prepare("INSERT INTO uploaded_files (file_name, file_path) VALUES (?, ?)"); $stmt->bind_param("ss", $uniqueName, $targetPath); $stmt->execute(); $response[] = [ "name" => $name, "path" => $targetPath, "status" => "uploaded" ]; } else { $response[] = [ "name" => $name, "status" => "failed", "message" => "Error moving uploaded file." ]; }
}
echo json_encode(["success" => true, "files" => $response]);
?>

Drop area to place the dragged files

It contains UI elements to define the file drop area. The drop box uses onDragOver callback to highlight the drop area on hover.

And, the onDrop callback prepares the form data to post the dropped file binary to the server.

react file upload error state

src/components/UploadBox.jsx

const UploadBox = ({ dragActive, uploading, errorMsg, handleDrop, setDragActive }) => ( <> <div className={`upload-box ${dragActive ? "active" : ""}`} onDragOver={(e) => { e.preventDefault(); setDragActive(true); }} onDragLeave={() => setDragActive(false)} onDrop={handleDrop} > <h3 className="upload-title">Drag & Drop Files Here</h3> <p className="upload-text">Files will upload automatically</p> </div> {uploading && <p className="uploading-text">Uploading...</p>} {errorMsg && <p className="error-text">{errorMsg}</p>} </>
); export default UploadBox;

Showing file preview with thumbnails

The FilePreview component displays the uploaded files in a list format. It will show its thumbnail, name and size.

If an image upload, the preview will show the image thumbnail. It a document type file is uploaded, the default icon is shown to the preview screen.
React File Upload Success Case Output

src/components/FilePreview.jsx

const FilePreview = ({ files, uploading }) => { if (!files.length) return null; return ( <div className="preview-list"> {files.map((file, i) => ( <div key={i} className="preview-row"> {file.type?.startsWith("image/") ? ( <div className="preview-thumb-wrapper"> <img src={URL.createObjectURL(file)} alt={file.name} className={`preview-thumb ${uploading ? "blurred" : ""}`} /> {uploading && ( <div className="preview-loader"> <img src="/assets/image/loader.svg" alt="Loading..." /> </div> )} </div> ) : ( <div className="file-icon"></div> )} <div className="file-info"> <p className="file-name">{file.name}</p> <p className="file-size">{Math.round(file.size / 1024)} KB</p> </div> </div> ))} </div> );
};
export default FilePreview;

How to set up this application

The below steps help to set up this example to run in your environment. After these steps, start the npm dev server and run the React drag and drop app.

  1. Download the source and unzip into your computer.
  2. Copy the drag-drop-file-upload-api into the PHP web root.
  3. Create a database file_upload_db and import the SQL script in the drag-drop-file-upload-api/sql
  4. Configure database details with db.php
  5. Configure the PHP endpoint URL in React in src/config.js

Conclusion

I hope the React code provides a modern file upload interface. The drag-and-drop, file validation, preview rendering and database insert is a stack of features enriches the example code. This code well-structured and ready to integrate with an application easily. If you want any add-on feature to this example, please let me know.

References:

  1. HTML drag and drop UI
  2. Axios API request config option

Download

Vincy
Written by Vincy, a web developer with 15+ years of experience and a Masters degree in Computer Science. She specializes in building modern, lightweight websites using PHP, JavaScript, React, and related technologies. Phppot helps you in mastering web development through over a decade of publishing quality tutorials.

↑ Back to Top

Posted on Leave a comment

Upload and Display Image in PHP

by Vincy. Last modified on July 5th, 2023.

PHP upload is a single-line, built-in function invocation. Any user inputs, especially files, can not be processed without proper filtering. Why? Because people may upload harmful files to the server.

After file upload, the status has to be shown in the UI as an acknowledgment. Otherwise, showing the uploaded image’s preview is the best way of acknowledging the end user.

View Demo
Earlier, we saw how to show the preview of images extracted from a remote URL.

This article will provide a short and easy example in PHP to upload and display images.

upload and display image php

Steps to upload and display the image preview on the browser

  1. Show an image upload option in an HTML form.
  2. Read file data from the form and set the upload target.
  3. Validate the file type size before uploading to the server.
  4. Call the PHP upload function to save the file to the target.
  5. Display the uploaded image on the browser

1. Show an image upload option in an HTML form

This code is to show an HTML form with a file input to the user. This form is with enctype="multipart/form-data" attribute. This attribute is for uploading the file binary to be accessible on the PHP side.

<form action="" method="post" enctype="multipart/form-data"> <div class="row"> <input type="file" name="image" required> <input type="submit" name="submit" value="Upload"> </div>
</form>

Read file data from the form and set the upload target

This section shows a primary PHP condition to check if the form is posted and the file binary is not empty.

Once these conditions return true, further steps will be taken for execution.

Once the image is posted, it sets the target directory path to upload. The variable $uploadOK is a custom flag to allow the PHP file upload.

If the validation returns false, this $uploadOK variable will be turned to 0 and stop uploading.

<?php
if (isset($_POST["submit"])) { // Check image using getimagesize function and get size // if a valid number is got then uploaded file is an image if (isset($_FILES["image"])) { // directory name to store the uploaded image files // this should have sufficient read/write/execute permissions // if not already exists, please create it in the root of the // project folder $targetDir = "uploads/"; $targetFile = $targetDir . basename($_FILES["image"]["name"]); $uploadOk = 1; $imageFileType = strtolower(pathinfo($targetFile, PATHINFO_EXTENSION)); // Validation here }
}
?>

Validate the file type size before uploading to the server

This example applies three types of validation criteria on the server side.

  1. Check if the uploaded file is an image.
  2. Check if the image has the accepted size limit (0.5 MB).
  3. Check if the image has the allowed extension (jpeg and png).
<?php
// Check image using getimagesize function and get size // if a valid number is got then uploaded file is an image if (isset($_FILES["image"])) { // directory name to store the uploaded image files // this should have sufficient read/write/execute permissions // if not already exists, please create it in the root of the // project folder $targetDir = "uploads/"; $targetFile = $targetDir . basename($_FILES["image"]["name"]); $uploadOk = 1; $imageFileType = strtolower(pathinfo($targetFile, PATHINFO_EXTENSION)); $check = getimagesize($_FILES["image"]["tmp_name"]); if ($check !== false) { echo "File is an image - " . $check["mime"] . "."; $uploadOk = 1; } else { echo "File is not an image."; $uploadOk = 0; } } // Check if the file already exists in the same path if (file_exists($targetFile)) { echo "Sorry, file already exists."; $uploadOk = 0; } // Check file size and throw error if it is greater than // the predefined value, here it is 500000 if ($_FILES["image"]["size"] > 500000) { echo "Sorry, your file is too large."; $uploadOk = 0; } // Check for uploaded file formats and allow only // jpg, png, jpeg and gif // If you want to allow more formats, declare it here if ( $imageFileType != "jpg" && $imageFileType != "png" && $imageFileType != "jpeg" && $imageFileType != "gif" ) { echo "Sorry, only JPG, JPEG, PNG & GIF files are allowed."; $uploadOk = 0; }
?>

4. Call the PHP upload function to save the file to the target

Once the validation is completed, then the PHP move_uploaded_file() the function is called.

It copies the file from the temporary path to the target direct set in step 1.

<?php
// Check if $uploadOk is set to 0 by an error
if ($uploadOk == 0) { echo "Sorry, your file was not uploaded.";
} else { if (move_uploaded_file($_FILES["image"]["tmp_name"], $targetFile)) { echo "The file " . htmlspecialchars(basename($_FILES["image"]["name"])) . " has been uploaded."; } else { echo "Sorry, there was an error uploading your file."; }
}
?>

5. Display the uploaded image on the browser.

This section shows the image preview by setting the source path.

Before setting the preview source, this code ensures the upload status is ‘true.’

<h1>Display uploaded Image:</h1>
<?php if (isset($_FILES["image"]) && $uploadOk == 1) : ?> <img src="<?php echo $targetFile; ?>" alt="Uploaded Image">
<?php endif; ?>

Create a directory called “uploads” in the root directory of the downloaded example project. Uploaded images will be stored in this folder.

Note: The “uploads” directory should have sufficient file permissions.
View Demo Download

↑ Back to Top

Posted on Leave a comment

PHP Upload Image to Database with MySql

by Vincy. Last modified on July 2nd, 2023.

Do you want to upload an image to the database? Most application services move the uploaded files to a directory and save their path to the database.

Earlier, we saw code for storing uploaded images to the database using MySQL BLOB fields. BLOB(Binary Large Data Object) is one of the MySql data types. It can have the file binary data. MySQL supports four types of BLOB datatype as follows.
View demo

  1. TINYBLOB
  2. BLOB
  3. MEDIUMBLOB
  4. LONGBLOB

For this example, we created one of the above BLOB fields in a MySQL database to see how to upload an image. Added to that, this code will fetch and BLOB data from the database and display the image to the browser.

Database script

Before running this example, create the required database structure on your server.

CREATE TABLE images ( id INT(11) AUTO_INCREMENT PRIMARY KEY, image LONGBLOB NOT NULL );

php upload image to database output

HTML form with an image upload option

This is a usual file upload form with a file input. This field restricts the file type to choose only the images using the accept attribute.

On submitting this form, the upload.php receives the posted file binary data on the server side.

<!DOCTYPE html>
<html> <head> <title>PHP - Upload image to database - Example</title> <link href="style.css" rel="stylesheet" type="text/css" /> <link href="form.css" rel="stylesheet" type="text/css" />
</head> <body> <div class="phppot-container"> <h1>Upload image to database:</h1> <form action="upload.php" method="post" enctype="multipart/form-data"> <div class="row"> <input type="file" name="image" accept="image/*"> <input type="submit" value="Upload"> </div> </form> <h2>Uploaded Image (Displayed from the database)</h2> </div>
</body> </html>

Insert an image into the database using PHP and MySql

This PHP script gets the chosen file data with the $_FILES array. This array contains the base name, temporary source path, type, and more details.

With these details, it performs the file upload to the database. The steps are as follows,

  1. Validate file array is not empty.
  2. Retrieve the image file content using file_get_contents($_FILES[“image”][“tmp_name”]).
  3. Prepare the insert and bind the image binary data to the query parameters.
  4. Execute insert and get the database record id.
<?php
// MySQL database connection settings
$servername = "localhost";
$username = "root";
$password = "admin123";
$dbname = "phppot_image_upload"; // Make connection
$conn = new mysqli($servername, $username, $password, $dbname); // Check connection and throw error if not available
if ($conn->connect_error) { die("Connection failed: " . $conn->connect_error);
} // Check if an image file was uploaded
if (isset($_FILES["image"]) && $_FILES["image"]["error"] == 0) { $image = $_FILES['image']['tmp_name']; $imgContent = file_get_contents($image); // Insert image data into database as BLOB $sql = "INSERT INTO images(image) VALUES(?)"; $statement = $conn->prepare($sql); $statement->bind_param('s', $imgContent); $current_id = $statement->execute() or die("<b>Error:</b> Problem on Image Insert<br/>" . mysqli_connect_error()); if ($current_id) { echo "Image uploaded successfully."; } else { echo "Image upload failed, please try again."; }
} else { echo "Please select an image file to upload.";
} // Close the database connection
$conn->close();

Fetch image BLOB from the database and display to UI

This PHP code prepares a SELECT query to fetch the image BLOB. Using the image binary from the BLOB, it creates the data URL. It applies PHP base64 encoding on the image binary content.

This data URL is set as a source of an HTML image element below. This script shows the recently inserted image on the screen. We can also show an image gallery of all the BLOB images from the database.

<?php // Retrieve the uploaded image from the database $servername = "localhost"; $username = "root"; $password = ""; $dbname = "phppot_image_upload"; $conn = new mysqli($servername, $username, $password, $dbname); if ($conn->connect_error) { die("Connection failed: " . $conn->connect_error); } $result = $conn->query("SELECT image FROM images ORDER BY id DESC LIMIT 1"); if ($result && $result->num_rows > 0) { $row = $result->fetch_assoc(); $imageData = $row['image']; echo '<img src="data:image/jpeg;base64,' . base64_encode($imageData) . '" alt="Uploaded Image" style="max-width: 500px;">'; } else { echo 'No image uploaded yet.'; } $conn->close(); ?>

View demo Download

↑ Back to Top

Posted on Leave a comment

Gauge Chart JS – Speedometer Example

A gauge chart is a scale to measure performance amid the target. Yeah! My attempt at defining ‘Gauge.’ This article uses the ChartJS JavaScript library to create a gauge chat.

The below example creates a speedometer in the form of a gauge change. It achieves this with type=doughnut. The other options, cutout, rotation, and circumference, make the expected gauge chart view.
View Demo

<!DOCTYPE html>
<html> <head> <title>Gauge Chart Example using Chart.js</title> <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
</head> <body> <canvas id="gaugeChart"></canvas> <script> // data for the gauge chart // you can supply your own values here // max is the Gauge's maximum value var data = { value: 200, max: 300, label: "Progress" }; // Chart.js chart's configuration // We are using a Doughnut type chart to // get a Gauge format chart // This is approach is fine and actually flexible // to get beautiful Gauge charts out of it var config = { type: 'doughnut', data: { labels: [data.label], datasets: [{ data: [data.value, data.max - data.value], backgroundColor: ['rgba(54, 162, 235, 0.8)', 'rgba(0, 0, 0, 0.1)'], borderWidth: 0 }] }, options: { responsive: true, maintainAspectRatio: false, cutoutPercentage: 85, rotation: -90, circumference: 180, tooltips: { enabled: false }, legend: { display: false }, animation: { animateRotate: true, animateScale: false }, title: { display: true, text: data.label, fontSize: 16 } } }; // Create the chart var chartCtx = document.getElementById('gaugeChart').getContext('2d'); var gaugeChart = new Chart(chartCtx, config); </script>
</body> </html>

The above quick example script follows the below steps to render a gauge chart with the data and the options.

Many of the steps are similar to that of creating any other chart using this library. We have seen many examples in the ChartJS library. You can start with the ChartJS bar chart example if you are new to this JavaScript library.

The data and options are the main factors that change the chart view. This section has short notes for more information about the data and the options array created in JavaScript.

This JavaScript example uses an array of static data to form a gauge chart. You can supply dynamic data from the database or any external source instead.

The data array has the chart label, target, and current value. The target value is the maximum limit of the gauge chart scale. The current value is an achieved point to be marked.

Using these values, this script prepares the gauge chart dataset.

The options array is a configuration that affects the chart’s appearance.

The ChartJS allows featured configurations to experience the best chart views. Some of those options exclusive to the gauge chart are listed below.

Posted on Leave a comment

JavaScript – How to Open URL in New Tab

by Vincy. Last modified on June 25th, 2023.

Web pages contain external links that open URLs in a new tab. For example, Wikipedia articles show links to open the reference sites in a new tab. This is absolutely for beginners.

There are three ways to open a URL in a new tab.

  1. HTML anchor tags with target=_blank  attribute.
  2. JavaScript window.open() to set hyperlink and target.
  3. JavaScript code to create HTML link element.

HTML anchor tags with target=_blank  attribute

This is an HTML basic that you are familiar with. I added the HTML with the required attributes since the upcoming JavaScript example works with this base.

<a href="https://www.phppot.com" target="_blank">Go to Phppot</a>

Scenarios of opening URL via JavaScript.

When we need to open a URL on an event basis, it has to be done via JavaScript at run time. For example,

  1. Show the PDF in a new tab after clicking generate PDF link. We have already seen how to generate PDFs using JavaScript.
  2. Show product page from the gallery via Javascript to keep track of the shopping history.

The below two sections have code to learn how to achieve opening URLs in a new tab using JavaScript.

javascript open in new tab

JavaScript window.open() to set hyperlink and target

This JavaScript one-line code sets the link to open the window.open method. The second parameter is to set the target to open the linked URL in a new tab.

window.open('https://www.phppot.com', '_blank').focus();

The above line makes opening a URL and focuses the newly opened tab.

JavaScript code to create HTML link element.

This method follows the below steps to open a URL in a new tab via JavaScript.

  • Create an anchor tag (<a>) by using the createElement() function.
  • Sets the href and the target properties with the reference of the link object instantiated in step 1.
  • Trigger the click event of the link element dynamically created via JS.
var url = "https://www.phppot.com";
var link = document.createElement("a");
link.href = url;
link.target = "_blank";
link.click();

Browsers support: Most modern browsers support the window.open() JavaScript method.

↑ Back to Top

Share this page

Posted on Leave a comment

File Upload using Dropzone with Progress Bar

by Vincy. Last modified on June 30th, 2023.

Most of the applications have the requirement to upload files to the server. In previous articles, we have seen a variety of file upload methods with valuable features.

For example, we learned how to upload files with or without AJAX, validate the uploaded files, and more features.

This tutorial will show how to code for file uploading with a progress bar by Dropzone.

View demo

If the file size is significant, it will take a few nanoseconds to complete. Showing a progress bar during the file upload is a user-friendly approach.

To the extreme, websites start showing the progressing percentage of the upload. It is the best representation of showing that the upload request is in progress.

dropzone progress bar

About Dropzone

The Dropzone is a JavaScript library popularly known for file uploading and related features. It has a vast market share compared to other such libraries.

It provides a massive list of features. Some of the attractive features are listed below.

  • It supports multi-file upload.
  • It represents progressing state and percentage.
  • It allows browser image resizing. It’s a valuable feature that supports inline editing of images.
  • Image previews in the form of thumbnails.
  • It supports configuring the uploaded file’s type and size limit.

How to integrate dropzone.js to upload with the progress bar

Integrating Dropzone into an application is simple. It is all about keeping these two points during the integration.

  1. Mapping the UI element with the Dropzone initiation.
  2. Handling the upload event callbacks effectively.

Mapping the UI element with the Dropzone initiation

The below code has the HTML view to show the Dropzone file upload to the UI. It includes the Dropzone JS and the CSS via a CDN URL.

<!DOCTYPE html>
<html> <head> <title>File Upload using Dropzone with Progress Bar</title> <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/dropzone/5.9.2/dropzone.min.css"> <style> .progress { width: 300px; border: 1px solid #ddd; padding: 5px; } .progress-bar { width: 0%; height: 20px; background-color: #4CAF50; } </style> <link rel="stylesheet" type="text/css" href="style.css" /> <link rel="stylesheet" type="text/css" href="form.css" />
</head> <body> <div class="phppot-container tile-container text-center"> <h2>File Upload using Dropzone with Progress Bar</h2> <form action="upload.php" class="dropzone" id="myDropzone"></form> </div> <script src="https://cdnjs.cloudflare.com/ajax/libs/dropzone/5.9.2/min/dropzone.min.js"></script>
</body> </html>

The file upload form element is mapped to the DropzoneJS while initiating the library.

The form action targets the PHP endpoint to handle the file upload.

Dropzone.options.myDropzone = { //Set upload properties init: function () { // Handle upload event callback functions }; };

Handling the upload event callbacks

This section has the Dropzone library script to include in the view. This script sets the file properties and limits to the upload process. Some of the properties are,

  • maxFilesize – Maximum size allowed for the file to upload.
  • paramName – File input name to access like $_FILE[‘paramName here’].
  • maxFiles – File count allowed.
  • acceptedFiles – File types or extensions allowed.

The init property of this script allows handling the upload event. The event names are listed below.

  • uploadprogress – To track the percentage of uploads to update the progress bar.
  • success – When the file upload request is completed. This is as similar to a jQuery AJAX script‘s success/error callbacks.

Dropzone options have the upload form reference to listen to the file drop event. The callback function receives the upload status to update the UI.

The dropzone calls the endpoint action when dropping the file into the drop area.

The drop area will show thumbnails or a file preview with the progress bar.

Dropzone.options.myDropzone = { paramName: "file", // filename handle to upload maxFilesize: 2, // MB maxFiles: 1, // number of files allowed to upload acceptedFiles: ".png, .jpg, .jpeg, .gif", // file types allowed to upload init: function () { this.on("uploadprogress", function (file, progress) { var progressBar = file.previewElement.querySelector(".progress-bar"); progressBar.style.width = progress + "%"; progressBar.innerHTML = progress + "%"; }); this.on("success", function (file, response) { var progressBar = file.previewElement.querySelector(".progress-bar"); progressBar.classList.add("bg-success"); progressBar.innerHTML = "Uploaded"; }); this.on("error", function (file, errorMessage) { var progressBar = file.previewElement.querySelector(".progress-bar"); progressBar.classList.add("bg-danger"); progressBar.innerHTML = errorMessage; }); } };

PHP file upload script

This a typical PHP file upload script suite for any single file upload request. But, the dependent changes are,

  1. File handle name ($_FILES[‘File handle name’]).
  2. Target directory path for $uploadDir variable.
<?php if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['file'])) { $file = $_FILES['file']; // file to be uploaded to this directory // should have sufficient file permissions $uploadDir = 'uploads/'; // unique file name generated for the uploaded file $fileName = uniqid() . '_' . $file['name']; // moving the uploaded file from temp directory to uploads directory if (move_uploaded_file($file['tmp_name'], $uploadDir . $fileName)) { echo 'File uploaded successfully.'; } else { echo 'Failed to upload file.'; }
}

How to hide the progress bar of uploaded files

By default, the Dropzone JS callback adds a dz-complete CSS class selector to the dropzone element. It will hide the progress bar from the preview after a successful upload.

This default behavior is by changing the progress bar opacity to 0. But the markup will be there in the source. Element hide and show can be done in various ways.

If you want to remove the progress bar element from the HTML preview, use the JavaScript remove() function. This script calls it for the progress bar element on the success callback.

Dropzone.options.myDropzone = { ... ... init: function () { ... ... this.on("success", function (file, response) { var progressBar = file.previewElement.querySelector(".progress-bar"); progressBar.remove(); }); ... ... }
};

View demo Download

↑ Back to Top