Hernandez’s winner came moments after Romelu Lukaku thought he had fired the Belgians through to the final only for his goal to be disallowed by VAR for a marginal offside.
Belgium had looked set to cruise into a final meeting with Spain after a dominant first-half display capped by goals from Yannick Carrasco and Lukaku.
But two goals in six second-half minutes, from Karim Benzema and a Kylian Mbappe penalty, hauled the French back into the game and set up a grandstand finish.
Roberto Martinez’s men had set out their intentions from the start with Kevin De Bruyne and Lukaku working superbly to pin their opponents back on the counter-attack.
The Manchester City man met a Lukaku cross with a half-volley that was well saved by Hugo Lloris, then Eden Hazard was denied a fine chance in the box by a superb saving challenge from French defender Jules Kounde.
Still struggling for form after their early exit from Euro 2020, Didier Deschamps’ men were struggling to gain a foot-hold and they fell behind in the 37th minute when Carrasco drifted in from the left and drilled his shot inside Lloris.
Two minutes later De Bruyne fed Lukaku, who spun off Lucas Hernandez and fired past Lloris – and the French goalkeeper had to be alert to deny Hazard a third for Belgium before half-time.
Benzema’s brilliant finish from another Mbappe ball gave France the goal they deserved in the 62nd minute, and six minutes later Mbappe fired his spot-kick into the top corner after Griezmann was tripped by Youri Tielemans in the box.
Belgium responded, with Lukaku bringing two fine saves out of Lloris, before Carrasco’s cross into the box was met by the Chelsea forward, who volleyed what he thought was the winner three minutes from time.
But VAR declared otherwise and there was still time for France to sweep up the other end, where Benjamin Pavard’s ball into the box was deflected and fell to Theo Hernandez to drill his first international goal and seal his side’s place in the final.