Here is my store.js:-
import { configureStore } from "@reduxjs/toolkit";
import authSlice from "./authSlice";
export const store = configureStore(
{
reducer: {auth: authSlice.reducer}
}
)
Here is my index.js:-
import React from 'react';
import { createRoot } from 'react-dom/client';
import { Provider } from 'react-redux';
import { store } from './app/store';
import App from './App';
import './index.css';
const container = document.getElementById('root');
const root = createRoot(container);
root.render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>
);
Here is my authSlice.js:-
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
import authService from './authService';
const localuser = JSON.parse(localStorage.getItem('user'));
//initial state for the authentication slice
const initialState = {
user: localuser ? localuser : null,
isError: false,
isSuccess: false,
isLoading: false,
message: ''
}
export const register = createAsyncThunk( // thunk for dispatching actions(TYPE) and managing API calls (like for registering user)
'auth/register', //unique identifier for this thunk
async (user, thunkAPI) => { //payload creator that returns a result by performing a action of API call
try {
return await authService.register(user)
} catch (error) {
const message = (error.response && error.response.data && error.response.data.message) || error.message || error.toString()
return thunkAPI.rejectWithValue(message)
}
}
)
// Creating the authentication slice
export const authSlice = createSlice({
name: 'auth', //name of the slice
initialState, //initial state of this slice
reducers: {
//reducer function to reset the state
reset: (state) => {
state.isLoading = false
state.isSuccess = false
state.isError = false
state.message = ''
},
},
// takes a object i.e. builder with cases such as pending, etc and states are updated.
extraReducers: builder => {
builder.addCase(register.pending, (state)=>{
state.isLoading = true;
})
builder.addCase(register.fulfilled, (state, action) => {
state.isLoading = false;
state.isSuccess = true;
state.user = action.payload;
})
builder.addCase(register.rejected, (state, action)=>{
state.isLoading = false;
state.isError = true;
state.message = action.payload;
state.user = null;
})
}
})
//exporting the actions and reducers
export const { reset } = authSlice.actions;
export default authSlice;
Here is my authService.js:-
import axios from 'axios';
const API_URI = '/api/users';
const register = async(userData) => {
const response = await axios.post(API_URI, userData);
if (response.data) {
localStorage.setItem('user', JSON.stringify(response.data));
}
return response.data;
}
const authService = { register }
export default authService;
Here is my Register.js where I have used the useSelector:-
import React, { useEffect, useState } from "react";
import {useDispatch} from "react-redux";
import { useSelector } from "react-redux";
import {useNavigate} from "react-router-dom";
import {register, reset} from "../features/auth/authSlice";
export default function Register(){
const [formData, setFormData] = useState({ name: '', email: '', password: '', password2: ''});
const {name, email, password, password2} = formData;
const navigate = useNavigate();
const dispatch = useDispatch();
const {user, isLoading, isError, isSuccess, message} = useSelector(state => state.auth);
return(
<div>
<section className="heading">
<h1><FaUser/> Register</h1>
<p>Please create a account</p>
</section>
<section className="form">
<form onSubmit={onSubmit}>
<div className="form-group">
<input type="text" className="form-control" id="name" name="name" value={name} placeholder="Enter your name" onChange={onChange}/>
</div>
<div className="form-group">
<input type="email" className="form-control" id="email" name="email" value={email} placeholder="Enter your email" onChange={onChange}/>
</div>
<div className="form-group">
<input type="password" className="form-control" id="password" name="password" value={password} placeholder="Enter your password" onChange={onChange}/>
</div>
<div className="form-group">
<input type="password" className="form-control" id="password2" name="password2" value={password2} placeholder="Confirm password" onChange={onChange}/>
</div>
<div className="form-group">
<button type="submit" className="btn btn-block">Submit</button>
</div>
</form>
</section>
</div>
)
This is error I am getting in Register.js:-
Uncaught runtime errors:
×
ERROR
Cannot destructure property ‘user’ of ‘(0 , react_redux__WEBPACK_IMPORTED_MODULE_1__.useSelector)(…)’ as it is undefined.
TypeError: Cannot destructure property ‘user’ of ‘(0 , react_redux__WEBPACK_IMPORTED_MODULE_1__.useSelector)(…)’ as it is undefined.
What I tried is by including OR condition in this line which is inside Register.js:-
const {user, isLoading, isError, isSuccess, message} = useSelector(state => state.auth || {});
And then when I click on Submit button to register, then I get one more error that is this:-
proxy error: Could not proxy request /api/users from localhost:3000 to http://localhost:8000/.
See https://nodejs.org/api/errors.html#errors_common_system_errors for more information (ECONNREFUSED)
I have also included proxy in the package.json file but still I am getting the above error:
My Package.json of the frontend folder:
{
"name": "frontend",
"version": "0.1.0",
"proxy": "http://localhost:8000",
"private": true,
"dependencies": {
"@reduxjs/toolkit": "^1.9.7",
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^14.5.2",
"axios": "^1.7.2",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-icons": "^5.2.1",
"react-redux": "^8.1.3",
"react-router-dom": "^6.24.0",
"react-scripts": "5.0.1",
"react-toastify": "^10.0.5",
"web-vitals": "^2.1.4"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
Can someone help me out with this ? What am I missing ? Or am I doing something wrong ?