How to rewrite simple project in React

I have a simple project where you start at a register page which has validation checks. When you finally register you should have your session saved (not implemented yet, should be done with React locally I think) and go to another page where you can play tic tac toe.

I have the register page and the tic tac toe page. I’m pretty new to React. I’m just trying to practice by implementing it with React, but I can’t get it to work. And I’m still puzzled about the local session saving and I’m not quite sure how to do that either.

Code:

REGISTER PAGE:

index.html:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <script type="text/javascript" src="script.js"></script>
        <link rel="stylesheet" type="text/css" href="styles.css">
        <title>Project</title>
    </head>
    <body>
        <div id="error" class="noerror"></div>
        
        <div class="container">
            <form onsubmit="return validate()" action="tictactoe.html" method="post" class="regform">
                <span class="registration">Registration</span>
                
                <input type="user" id="user" name="user" placeholder="Username">
                <input type="password" id="password" name="password" placeholder="Password">
                <input type="password" id="password2" name="password2" placeholder="Confirm password">
                
                <input type="submit" id="submit" value="Register">
            </form>
        </div>
    </body>
</html>

styles.css:

.container {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 95vh;
}

.regform {
    display: flex;
    flex-flow: column wrap;
    width: 400px;
    padding: 20px;
    background-color: whitesmoke;
    border: 1px solid black;
}

.registration {
    background-color: yellowgreen;
    color: white;
    text-align: center;
    padding: 10px;
    margin: -21px -21px 10px -21px;
    text-transform: uppercase;
    font-weight: bold;
}

.error {
    word-wrap: normal;
    background-color: orangered;
    font-weight: bold;
    text-align: center;
    padding: 10px;
    margin-left: 5%;
    margin-right: 5%;
}

.noerror {
    display: hidden;
}

input {
    padding: 10px;
    margin: 10px 0px;
    border: 1px solid lightgrey;
}

input#submit {
    background-color: yellowgreen;
    color: white;
}

* {
    font-family: Arial, Helvetica, sans-serif;
}

script.js:

function validate() {
    var user = document.getElementById('user').value;
    var pass = document.getElementById('password').value;
    var pass2 = document.getElementById('password2').value;
    
    if(!/^[a-zA-Z0-9_]{3,16}$/.test(user)) {
        var msg = 'Username must be between 3 and 16 symbols. Can only contain lowercase and uppercase letters, one number and "_"!';
        showError(msg);
        return false;
    }
    
    if(!/^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{8,256}$/.test(pass)) {
        var msg = 'Password must be between 8 and 256 symbols. Must contain atleast one lowercase and uppercase letter, one number and one symbol!';
        showError(msg);
        return false;
    }
    
    if(pass != pass2) {
        var msg = 'Passwords must match.';
        showError(msg);
        return false;
    }
}

function showError(msg) {
    document.getElementById('error').innerHTML = msg;
    document.getElementById('error').classList.add('error');
    document.getElementById('error').classList.remove('noerror');
}

TIC TAC TOE PAGE:

tictactoe_script.js:

var x = '10006';
var o = '9898';

var firstPlayerMove;
var gameWon;
var moves;

function showMsg(msg) {
    document.getElementById("msg").innerHTML = msg;
}

function setup() {
    firstPlayerMove = true;
    gameWon = false;
    moves = 0;
    showMsg("It's X's turn.");
}

function restart() {
    Array.prototype.forEach.call(document.getElementsByClassName("tile"), function(element) {
        element.innerHTML = "";
    });
    
    setup();
}

function makeMove(tile) {
    if(gameWon) {
        return false;
    }
    
    if(isValidMove(tile)) {
        moves++;
        
        if(firstPlayerMove) {
            tile.innerHTML = '&#' + x + ';';
        }
        else {
            tile.innerHTML = '&#' + o + ';';
        }
        
        if(checkWin()) {
            return true;
        }
        
        if(moves == 9) {
            showMsg("Draw.");
            return true;
        }
        
        firstPlayerMove = !firstPlayerMove;
        
        if(firstPlayerMove) {
            showMsg("It's X's turn.");
        }
        else {
            showMsg("It's O's turn.");
        }
    }
}

function isValidMove(tile) {
    return tile.innerHTML === '';
}

function checkWin() {
    var tiles = document.getElementsByClassName("tile");
    var xTiles = new Array(9);
    var oTiles = new Array(9);
    
    for(var i = 0; i < tiles.length; i++) {
        if(tiles[i].innerHTML === String.fromCharCode(x)) {
            xTiles[i] = 1;
        }
        
        if(tiles[i].innerHTML === String.fromCharCode(o)) {
            oTiles[i] = 1;
        }
    }
    
    if(hasWinningPattern(xTiles)) {
        showMsg("Player 1 (X) won.");
        return true;
    }
    
    if(hasWinningPattern(oTiles)) {
        showMsg("Player 2 (O) won.");
        return true;
    }
    
    return false;
}

function hasWinningPattern(tiles) {
    var winningPatterns = [
        [0, 1, 2],
        [3, 4, 5],
        [6, 7, 8],
        [0, 3, 6],
        [1, 4, 7],
        [2, 5, 8],
        [0, 4, 8],
        [2, 4, 6]
    ];
    
    for(var i = 0; i < winningPatterns.length; i++) {
        var pattern = winningPatterns[i];
        
        var win = true;
        for(var j = 0; j < pattern.length; j++) {
            if(tiles[pattern[j]] != 1) {
                win = false;
            }
        }
        
        if(win) {
            gameWon = true;
            return true;
        }
    }
    
    return false;
}

tictactoe_styles.css:

.board, .start, .msg {
    position: absolute;
    margin: auto;
    left: 0;
    right: 0;
    top: 0;
    bottom: 0;
}

.board {
        margin-top: 110px;
    width: 600px;
    height: 600px;
    border: 1px solid lightgrey;
    font-size: 0px;
    max-width: 100%;
    max-height: 100%;
}
 
.row {
    width: 600px;
    height: 200px;
    font-size: 0px;
}
 
.tile {
    border: 1px solid lightgrey;
    width: 198px;
    height: 200px;
    display: inline-block;
    font-size: 150px;
    text-align: center;
    vertical-align: middle;
    line-height: 200px;
}

.tile:hover {
    background-color: grey;
}

.start {
    width: 100px;
    height: 50px;
    margin-top: 50px;
}

.msg {
    width: 300px;
    height: 50px;
    margin-top: 10px;
    font-size: 32px;
    font-weight: bold;
    text-align: center;
    font-family: Arial, Helvetica, sans-serif;
}

tictactoe.html:

<html>
    <head>
        <meta charset="UTF-8" />
        <title>Project</title>
        <link rel="stylesheet" type="text/css" href="tictactoe_styles.css">
        <script src="tictactoe_script.js"></script>
    </head>
    <body onload="setup()">
        <button onclick="restart()" class="start">Restart</button>
        <div class="board">
            <div class="row">
                <div onclick="makeMove(this)" class="tile"></div>
                <div onclick="makeMove(this)" class="tile"></div>
                <div onclick="makeMove(this)" class="tile"></div>
            </div>
            <div class="row">
                <div onclick="makeMove(this)" class="tile"></div>
                <div onclick="makeMove(this)" class="tile"></div>
                <div onclick="makeMove(this)" class="tile"></div>
            </div>
            <div class="row">
                <div onclick="makeMove(this)" class="tile"></div>
                <div onclick="makeMove(this)" class="tile"></div>
                <div onclick="makeMove(this)" class="tile"></div>
            </div>
        </div>
        <div class="msg" id="msg"></div>
    </body>
</html>

This is all of the code and it works fine. Here is how I tried to implement the register page on react but failed:

index.js:

//import React, { Fragment } from 'react';
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
//import App from './App';
import reportWebVitals from './reportWebVitals';

import { useState } from 'react';

function Register() {
  const[msg, setMessage] = useState('');
  const [user, setUser] = useState('');
  const [pass, setPass] = useState('');
  const [pass2, setPass2] = useState('');

  function validate() {
    if(!/^[a-zA-Z0-9_]{3,16}$/.test(user)) {
      setMessage('Username must be between 3 and 16 symbols. Can only contain lowercase and uppercase letters, one number and "_"!');
    }
    
    if(!/^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{8,256}$/.test(pass)) {
      setMessage('Password must be between 8 and 256 symbols. Must contain atleast one lowercase and uppercase letter, one number and one symbol!');
    }
    
    if(pass !== pass2) {
      setMessage('Passwords must match.');
    }
  }
  
  return (<>
    <div class="container">
      <div id="error" class="error">{msg}</div>
            
                <span class="registration">Registration</span>
                
                <input onchange={()=>setUser} type="user" id="user" name="user" placeholder="Username"/>
                <input onchange={()=>setPass} type="password" id="password" name="password" placeholder="Password"/>
                <input onchange={()=>setPass2} type="password" id="password2" name="password2" placeholder="Repeat Password"/>
                
                <input onchange={()=>validate()} type="button" id="submit" value="Register"/>
            
        </div>
  </>)
}

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <Register/>
);

If someone could help me implement the code in React that would be great! Any help is greatly appreciated! Thanks in advance!