@nyahera Just a hunch... on mobile, some other div's (hidden or margin) may be overlapping your REGISTER button. That's why maybe nothing happens when you tap it on mobile. Please inspect the mobile view and check. This may solve the issue.
Why is my react registration form not working on mobile devices when in production but works well on desktop or laptop?
I am working on authentication project build using laravel 11 api and react with vite for frontend. The problem is, when I deploy the project to cpanel and test the registration form. It works just fine on desktops but when I open the register page on mobile browser and try to click on the register button, nothing happens and no error is shown in the console. Am stuck and don't know what to do. Am using axios with react to post data.
The register forms displays very well but when you click on register to register a user on mobile phone nothing happens, but on laptop it registers users very well.
Am using laravel vite plugin for my react app, and laravel 11 for my api with sanctum token for authentication.
Secondly, in development, when POST data is send using axios errors are consoled in the catch section but in production errors are consoled in .then why so, I cant understand. sorry am new to this stuff may not have used the words appropriately.
@experimentor thanks for that, but the button works well if I use Formik for client side validation I see the errors well, when it comes to showing errors from laravel api in production and on mobile browsers alone or registering user into the database nothing happens.
@nyahera In that case please share your controller and frontend code (axios part). Hopefully someone will be able to solve it after looking at the code.
my frontend code
import React, { useState } from "react";
import axiosClient from "../../../axiosClients/axiosClient";
import { useFormik } from "formik";
import PhoneInput from "react-phone-input-2";
export default function Register() {
const [regerrors, setRegErrors] = useState([]);
const [regsuccess, setRegSuccess] = useState([]);
function userRegister(payload) {
axiosClient
.post("/V1/auth/register", payload)
.then((response) => {
console.log("user datta", response.data);
if (response.data.success === false) {
setRegSuccess("");
setRegErrors(response.data.errors);
} else {
setRegSuccess(response.data.message);
setRegErrors({});
}
})
.catch((err) => {
if (err && err.response) {
if (err.response.data.errors) {
console.log("register eror ", err.response);
setRegErrors(err.response.data.errors);
setRegSuccess("");
} else {
setRegErrors(err.response.data.message);
setRegSuccess("");
}
}
});
}
const regFormik = useFormik({
initialValues: {
name: "",
email: "",
phone: "",
age: "",
password: "",
confirm_password: "",
},
validateOnBlur: true,
onSubmit: userRegister,
});
const onValueChange = (phoneNumber) => {
regFormik.setFieldValue("phone", phoneNumber);
};
return (
<div className="container">
<div className="row" style={{ backgoundColor: "red" }}>
<div className="col-ls-6 col-ms-6 m-auto">
<div className="register-boxu">
<div className="card card-outline card-primary">
<div className="card-body">
<p className="login-box-msg">
Register a new membership
</p>
{regsuccess ? (
<p className="stardy_form_success">
{regsuccess}
</p>
) : (
""
)}
<form
method="post"
onSubmit={regFormik.handleSubmit}
>
<div className="row">
<div className="col-sm-6">
<div className="form-group">
<input
type="text"
onChange={
regFormik.handleChange
}
value={
regFormik.values.name
}
onBlur={
regFormik.handleBlur
}
name="name"
id="name"
className="form-control"
placeholder="First Name..."
/>
<span className="stardy_errors">
{regFormik.touched.name &&
regFormik.errors.name
? regFormik.errors.name
: ""}
</span>
{regerrors?.name && (
<span className="stardy_errors">
{regerrors.name[0]}
</span>
)}
</div>
</div>
<div className="col-sm-6">
<div className="form-group">
<input
type="email"
onChange={
regFormik.handleChange
}
value={
regFormik.values.email
}
onBlur={
regFormik.handleBlur
}
name="email"
id="email"
className="form-control"
placeholder="Email"
/>
<span className="stardy_errors">
{regFormik.touched.email &&
regFormik.errors.email
? regFormik.errors.email
: ""}
</span>
{regerrors?.email && (
<span className="stardy_errors">
{regerrors.email[0]}
</span>
)}
</div>
</div>
</div>
<div className="row">
<div className="col-sm-6">
<div className="form-group">
<PhoneInput
inputProps={{
name: "phone",
}}
onBlur={
regFormik.handleBlur
}
onChange={onValueChange}
country="ke"
/>
<span className="stardy_errors">
{regFormik.touched.phone &&
regFormik.errors.phone
? regFormik.errors.phone
: ""}
</span>
{regerrors?.phone && (
<span className="stardy_errors">
{regerrors.phone[0]}
</span>
)}
</div>
</div>
<div className="col-sm-6">
<div className="form-group">
<select
className="custom-select rounded-0"
onChange={
regFormik.handleChange
}
value={regFormik.values.age}
onBlur={
regFormik.handleBlur
}
id="age"
name="age"
>
<option value="" hidden>
Age
</option>
<option value="18-25 years">
18-25 years
</option>
<option value="26-35 years">
26-35 years
</option>
<option value="Above 35 years">
Above 35 years
</option>
</select>
<span className="stardy_errors">
{regFormik.touched.age &&
regFormik.errors.age
? regFormik.errors.age
: ""}
</span>
{regerrors?.age && (
<span className="stardy_errors">
{regerrors.age[0]}
</span>
)}
</div>
</div>
</div>
<div className="row">
<div className="col-sm-6">
<div className="form-group">
<input
type="password"
name="password"
id="password"
onChange={
regFormik.handleChange
}
value={
regFormik.values
.password
}
onBlur={
regFormik.handleBlur
}
className="form-control"
placeholder="Password"
/>
<span className="stardy_errors">
{regFormik.touched
.password &&
regFormik.errors.password
? regFormik.errors
.password
: ""}
</span>
{regerrors?.password && (
<span className="stardy_errors">
{regerrors.password[0]}
</span>
)}
</div>
</div>
<div className="col-sm-6">
<div className="form-group">
<input
type="password"
name="confirm_password"
id="confirm_password"
onChange={
regFormik.handleChange
}
value={
regFormik.values
.confirm_password
}
onBlur={
regFormik.handleBlur
}
className="form-control"
placeholder="Confirm Password"
/>
<span className="stardy_errors">
{regFormik.touched
.confirm_password &&
regFormik.errors
.confirm_password
? regFormik.errors
.confirm_password
: ""}
</span>
{regerrors?.confirm_password && (
<span className="stardy_errors">
{
regerrors
.confirm_password[0]
}
</span>
)}
</div>
</div>
</div>
<div className="row">
<div className="col-7"></div>
<div className="col-5">
<button
type="submit"
className="btn btn-primary btn-block"
>
Register
</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
);
}
from controller
class ApiAuthController extends Controller
{
public function __construct(private readonly UserService $userService){
}
public function register(RegisterRequest $request){
$userDto=UserDto::fromApiFormRequest($request);
$user = $this->userService->createUser($userDto);
return response()->json(['success'=>true, 'message'=>'Registration was successful, check your email inbox or Spam folder for a verifification link to activate your acount']);
}
}
If you are setting the validation rules in RegisterRequest, the catch block in your frontend will get triggered for validation errors.
But, if you are setting 'success' => true/false in response()->json that will be visible in the .then() block.
Please try to post the code properly formatted using markdown.
@experimentor That's nice, but then with my code why is it that in production errors from RegisterRequest are being triggered in .then() block. Something is just wierd for me, development and production results are just quite different.
something interesting is, I am experiencing this with react when I use blade templates everything works very well.
@nyahera I'm not able to figure it out. Interesting issue indeed. Maybe someone else will be able to solve it. Let's try one more angle.. Do you have a custom instance of axios? from this line:
import axiosClient from "../../../axiosClients/axiosClient";
Maybe you have some interceptors on the axios client?
@experimentor yes here!
import axios from "axios";
const axiosClient = axios.create({
baseURL: "https://stardykenya.org/api",
// baseURL: "http://127.0.0.1:8001/api",
});
axiosClient.interceptors.request.use((config) => {
const token = localStorage.getItem("ACCESS_TOKEN");
config.headers.Authorization = `Bearer ${token}`;
return config;
});
axiosClient.interceptors.response.use(
(response) => {
return response;
},
(error) => {
try {
const { response } = error;
if (response.status === 401) {
localStorage.removeItem("ACCESS_TOKEN");
}
} catch (error) {
console.error(error);
}
throw error;
}
);
export default axiosClient;
@nyahera Axios documentation says that you have to return a rejected promise like so:
function (error) {
// Any status codes that falls outside the range of 2xx cause this function to trigger
// Do something with response error
return Promise.reject(error);
}
Reference: https://axios-http.com/docs/interceptors
Also please try placing a console.log in the interceptor "error" function to see if it is getting triggered.
I am not 100% sure that this will solve the issue. But given the asynchronous nature of javascript, i think it's worth a try.
Please or to participate in this conversation.