update props after use it - reactjs

I'm not good in react
but i code))
I have problem. My flow:
customer open "create new user" page -> then create user -> then redirect "Success" page.
after that when customer go to "create new user" page again, -> he go "Success" page without creating.
I know it is because i use props wrong way
how can I fix it?
my Component.js
class addUser extends Component {
handleSubmit(e) {
e.preventDefault();
const user = {
name: this.state.name,
}
this.props.newUser(user);
}
componentDidUpdate(prevProps, prevState){
const { isCreateNewUser } = this.props.isCreateNewUser;
if(isCreateNewUser == true) {
this.props.history.push('/')
}
}
render() {
<form className="add-new-post" autoComplete="off" onSubmit={ this.handleSubmit }>
</form>
}
my reducer.js
export const reducerSubscriptions = function(state = initialState, action) {
switch (action.type) {
case ADD_USER:
return {
...state,
isCreateNewUser: action.payload
}
}
}
my action.js
export const newUser = (subscription) => dispatch => {
axios.post('/api/user/add', subscription)
.then(res => {
dispatch({
type: ADD_USER,
payload: res.data
});
});
}

your problem seems like a props or state that don't return to his initial value
and
const { isCreateNewUser } = this.props.isCreateNewUser;
isCreateNewUser his an object? because when you destruct a non-object it should looks like this
const { isCreateNewUser } = this.props;
and where do you update isCreateNewUser to true

my solution:
my action.js
export const createUser = (user) => async dispatch => {
const res = await axios.post('/api/user/add', subscription);
dispatch({ type: SOME_ACTION_TYPE, payload: res });
return res;
}
my Component.js
this.props.createUser(user)
.then(data => {
if(data.data[0]){
this.props.history.push('/');
}
}).catch(error => {
console.log("error", error);
})
i don't know is it good or not but it works.
thanks

Related

react toastify with redux from axios API

i am trying to send the error messages that sent from my server ( express ) to axios and the error message displays in toastify component but the error message doesn't show up here is the login axios function with the toastify how can i display toastify message inside my page from redux ?
here is my code :
// redux controller
const login = async (username, password) => {
await axios.post("/login",{username,password,},
{ withCredentials: true });};
// reducer page
export function generateError(prop) {
return function (dispatch) {
dispatch({
type: "USER_FAIL"
});
toast.error(prop);
};
}
export function generateSuccess(prop) {
return function (dispatch) {
dispatch({
type: "USER_SUCCESS"
});
toast.success(prop);
};
}
export const login = createAsyncThunk(
"/login",
async ({ username, password }) => {
try {
const data = await authService.login(username, password);
if (data) {
if (data.errors) {
const { username, password } = data.errors;
if (username) generateError(username)
else if (password) generateError(password);
} else {
generateSuccess(data.success);
}
}
return { user: data };
} catch (error) {
console.log(error);
}
}
);
// login page
const handleSubmit = (e) => {
e.preventDefault();
dispatch(login({ username, password }));
}
i am using react-tostify and #redux-toolkit but the message doesn't display inside my page
i fixed it and here is my code :
// auth.js ( redux page )
export const login = createAsyncThunk(
"/login",
async ({ username, password }) => {
try {
const {data} = await axios.post(
"/login",
{
username,
password,
},
{ withCredentials: true }
);
return { user: data };
} catch (error) {
console.log(error);
}
});
const initialState = user
? { isLoggedIn: true, user }
: { isLoggedIn: false, user: null };
const authSlice = createSlice({
name: "auth",
initialState,
extraReducers: {
[login.fulfilled]: (state, action) => {
state.isLoggedIn = true;
state.user = action.payload.user;
},
[login.rejected]: (state, action) => {
state.isLoggedIn = false;
state.user = null;
},
[logout.fulfilled]: (state, action) => {
state.isLoggedIn = false;
state.user = null;
},
}})
const { reducer } = authSlice; export default reducer;
Login Page :
const { isLoggedIn } = useSelector((state) => state.auth);
const dispatch = useDispatch();
const handleSubmit = (e) => {
e.preventDefault();
dispatch(login({ username, password })).then(data => {
console.log(data)
if (data.payload.user) {
if (data.payload.user.errors) {
const { username, password } = data.payload.user.errors;
if (username) generateError(username)
else if (password) generateError(password);
} else {
generateSuccess(data.success);
navigate("/dashboard");
}
}
})
}
i realized when i back the data it has an object name payload i used it to get the error messages from express and then i put the message in toastify function gettingError and here it is
const generateError = error => {
toast.error(error, {
position: "bottom-right",
})
}
Hai I'm also looking for the same problem while searching I found a solution at with this : react-toastify-with-redux
my Code : authAction.js
import 'react-toastify/dist/ReactToastify.min.css';
import { toast} from 'react-toastify';
export const registerUser = (userData) => dispatch =>{
axios.post('user/register',userData)
.then(res=>toast.success('Your Account Created Successfully 👍'))
.then(res=> window.location = '/authentication/sign-in')
.catch(err=>dispatch(
{
type: GET_ERRORS,
payload: err.response.data
}
),toast.error("Error 😣"))
// .catch((err)=> {return })
};
On your signUp page just add
<ToastContainer />
That's all ...
This answer is probably late. But I came across this problem and decided to do it my way. I know there is toast. promise to handle promises and I don't want to call dispatch.then every time. So I can up with passing dispatch to my action wrapper. Here is my code.
// utils.ts
type ArgumentTypes<F extends CallableFunction> = F extends (
...args: infer A
) => any
? A[0]
: never;
export const withToast = <T = AnyAction | typeof createAsyncThunk>(
action: T,
{ pending, error, success }: ToastPromiseParams<T>
) => {
return (
dispatch: ReturnType<typeof useAppDispatch>,
actionParams?: ArgumentTypes<T & CallableFunction> | void
) => {
const promise = dispatch(
(action as CallableFunction)(actionParams as any)
).unwrap();
toast.promise(promise, {
pending,
error,
success,
});
};
};
// actions.ts
export const login = createAsyncThunk(
"user/login",
async (payload: {
email: string;
password: string;
}): Promise<Partial<LoginAPIResponse>> => {
const { data } = await axios.post(`${API}/${LOGIN_EP}/`, payload);
return data;
}
);
export const loginWithToast = withToast(login, {
pending: "Logging in...",
error: {
render: (error: any) => {
return error?.password || error?.email
? "Invalid email or password"
: "Something went wrong";
},
},
success: "Logged in successfully",
});
// usage in component
const dispatch = useAppDispatch();
loginWithToast(dispatch, {
email: values.email.value,
password: values.password.value,
});
First createAsyncThunk:
import { coreAxios } from "utilities/axios"; // Own customized axios
import { createAsyncThunk } from "#reduxjs/toolkit";
const BASE_URL = process.env.REACT_APP_MAIN_URL
export const GetProducts = createAsyncThunk(
"inventory/GetProducts",
async () => {
const {data} = await coreAxios.get(`${BASE_URL}/api/product/list/`);
return data
}
);
Second createSlice:
import { createSlice } from "#reduxjs/toolkit";
import { GetProducts } from "services/inventory/product.service";
import { toast } from 'react-toastify';
export const productSlice = createSlice({
name: "products",
initialState: {
productsList: [],
productsLoading: false,
productsError: null,
},
extraReducers:
(builder) => {
builder.addCase(GetProducts.pending, (state) => {
toast.loading('Promise is pending...')
state.productsLoading = true
});
builder.addCase(GetProducts.fulfilled, (state, action) => {
toast.dismiss();
toast.success('Promise resolved 👌');
state.productsList = action.payload
state.productsLoading = false
state.productsError = null
});
builder.addCase(GetProducts.rejected, (state, action) => {
toast.dismiss();
toast.error('Promise rejected 🤯 😣')
state.productsLoading = false
state.productsError = action.error?.message
});
},
});
export default productSlice.reducer;
Third page:
import { ToastContainer } from 'react-toastify';
import { useSelector, useDispatch } from "react-redux";
import { GetProducts } from 'services/inventory/product.service';
const Product = () => {
const { productsList, productsLoading, productsError } = useSelector((state) => state.products);
const dispatch = useDispatch();
useEffect(() => {
dispatch(GetProducts());
}, []);
return (
<div className="grid crud-demo">
<h1>Hello Alim</h1>
<ToastContainer />
</div>
);
}

Payload is undefined

I'm a PHP/Laravel mid-level developer. I'm totally a noob when it comes to react.js. Now I know that react uses API's and stuff to show data when it comes to laravel backend. I am used to traditional HTML, CSS, JS, Bootstrap, Ajax and whatsoever. I have a simple task to login a user from react through laravel backend. I'v created the APIs for that task and they're working totally fine and somehow I got lucky and attached those APIs ALL BY MYSELF (with a little research, of course). Now whenever I try to signin, I receive the usual data through an axios request to backend and have it in a variable signInUser. Now when I try to pass that data to other action function it's going undefined somehow. Here's my code so that you can understand what I'm trying to achieve:
Components\SignIn.js
constructor() {
super();
this.state = {
email: '',
password: ''
}
}
componentDidUpdate() {
if (this.props.showMessage) {
setTimeout(() => {
this.props.hideMessage();
}, 100);
}
if (this.props.authUser !== null) {
this.props.history.push('/');
}
}
render() {
const {email, password} = this.state;
const {showMessage, loader, alertMessage} = this.props;
return (
// other components and stuff...
<Button onClick={() => { this.props.showAuthLoader(); this.props.userSignIn({email, password});}} variant="contained" color="primary">
<IntlMessages id="appModule.signIn"/>
</Button>
);
}
const mapStateToProps = ({auth}) => {
const {loader, alertMessage, showMessage, authUser} = auth;
return {loader, alertMessage, showMessage, authUser}
};
export default connect(mapStateToProps, {
userSignIn,
hideMessage,
showAuthLoader
})(SignIn);
Sagas\Auth.js
const signInUserWithEmailPasswordRequest = async (email, password) =>
await axios.post('auth/login', {email: email, password: password})
.then(authUser => authUser)
.catch(err => err);
function* signInUserWithEmailPassword({payload}) {
const {email, password} = payload;
try {
const signInUser = yield call(signInUserWithEmailPasswordRequest, email, password);
if (signInUser.message) {
yield put(showAuthMessage(signInUser.message));
} else {
localStorage.setItem('user_id', signInUser.data.user.u_id);
yield put(userSignInSuccess(signInUser.data.user.u_id));
}
} catch (error) {
yield put(showAuthMessage(error));
}
}
export function* signInUser() {
yield takeEvery(SIGNIN_USER, signInUserWithEmailPassword);
}
export default function* rootSaga() {
yield all([fork(signInUser),
// couple of other functions...
);
}
actions\Auth.js
export const userSignIn = (user) => {
return {
type: SIGNIN_USER,
payload: user
};
};
export const userSignInSuccess = (authUser) => {
console.log(authUser); // It's printing undefined, I don't know why?!
return {
type: SIGNIN_USER_SUCCESS,
payload: authUser
}
};
reducers\Auth.js
const INIT_STATE = {
loader: false,
alertMessage: '',
showMessage: false,
initURL: '',
authUser: localStorage.getItem('user_id'),
};
export default (state = INIT_STATE, action) => {
switch (action.type) {
case SIGNIN_USER_SUCCESS: {
return {
...state,
loader: false,
authUser: action.payload
}
}
case INIT_URL: {
return {
...state,
initURL: action.payload
}
}
default:
return state;
}
}
P.s: It's a purchased react.js template (not my code).

Handling Local state and Redux State within a component

When a user tries to login, the Local state or Redux state should be updated. this.props.checkLogin() refers to the Redux store.
If the login is succesful, the Redux store should be updated.
Because this information is needed throughout the whole application.
If not succesful, the localstate should be updated with an error
message (a boolean which is called 'showError').
In the setup below, the results are always updated in the Redux store (which is not what I want, but I dont see any other solution yet). The main problem is that I can not catch an error in the checkLogin() of the component, if there is an error in the action.
// LOGIN COMPONENT (Code 1)
checkLogin(e){
e.preventDefault()
var username = e.target.elements.username.value
var password = e.target.elements.password.value
this.props.checkLogin(username, password)
}
// Redux action
export const checkLogin = (username, password) => async dispatch => {
axios.post('/api/login', {
username: username,
password: password
})
.then(res => {
const token = res.data.token;
localStorage.setItem('jwtToken', token);
setAuthorizationToken(token);
dispatch(setCurrentUser(jwt.decode(token)))
})
.catch(err => {
dispatch({
type: AUTH_ERROR,
payload: true
})
})
}
However, if there is an error in (Code 1), the Redux state is updated (with the AUTH_ERR action). I want to get rid of this action, as I only want it in local state. Because the boolean of an error login attempt should not be stored in Redux.
The only solution which I could think of is shown below (Code 2).
The POST-request has moved to the component itself (which is not nice in my opinion).
// LOGIN COMPONENT (Code 2)
checkLogin(e){
e.preventDefault()
var username = e.target.elements.username.value
var password = e.target.elements.password.value
axios.post('/api/login', {
username: username,
password: password
})
.then(res => {
this.props.checkLogin(username, password)
}
.catch(err => {
this.setState({
showError: true
})
})
}
// Redux action
export const checkLogin = (username, password) => async dispatch => {
const token = res.data.token;
localStorage.setItem('jwtToken', token);
setAuthorizationToken(token);
dispatch(setCurrentUser(jwt.decode(token)))
}
My main question is: what is the cleanest way of solving this? Is there some sort of guide which I can follow? The code (Code 2) works, but it definitely lacks design principles.
Another way of solving this could be something like this: use the first code and throw an error in the catch of the POST-request. Which is catched by the component, like this:
// LOGIN COMPONENT (Code 3)
checkLogin(e){
e.preventDefault()
var username = e.target.elements.username.value
var password = e.target.elements.password.value
this.props.checkLogin(username, password).catch(res => {
this.setState({
showError: true
})
})
}
// Redux action
export const checkLogin = (username, password) => async dispatch => {
axios.post('/api/login', {
username: username,
password: password
})
.then(res => {
const token = res.data.token;
localStorage.setItem('jwtToken', token);
setAuthorizationToken(token);
dispatch(setCurrentUser(jwt.decode(token)))
})
.catch(err => {
// Return an error here which is cacthed in the component
})
}
In the above code (Code 3), I can't see how to solve this. Is it possible to throw an error in the Redux action, which is then catched by the checkLogin() of the Login-component? Or should I complete take another path in solving this?
You have connected redux to manage the state of the application, why do you want to avoid storing an error in redux? A typical implementation of the react-redux (with redux-thunk middleware) authentication process is as follows.
actions.js
export const auth = (username, password) => {
dispatch(authStart())
axios.post('/api/login', {
username: username,
paswword: password
}).then(request => {
dispatch(authSuccess(response.authToken, response.userId))
}).catch(error => {
dispatch(authFail(error))
})
})
const authStart = () => {
return { type: 'AUTH_START'}
}
const authSuccess = (authToken, userId) => {
return { type: 'AUTH_SUCCESS', authToken: authToken, userId: userId }
}
const authFail = (error) => {
return { type: 'AUTH_FAIL', error: error }
}
reducer.js
const initialState = {
userId: null,
authToken: null,
error: null
loading: false
}
const authStart = (state, action) => {
return { ...state, loading: true, error: null }
}
const authSuccess = (state, action) => {
return {
...state,
loading: false,
authToken: action.authToken,
userId: actions.userId
}
}
const authStart = (state, action) => {
return { ...state, loading: false, error: error }
}
const authReducer = (state = initialState, action) => {
switch action.type:
case 'AUTH_START':
return authStart(state, action)
case 'AUTH_SUCCESS':
return authSuccess(state, action)
case 'AUTH_FAIL':
return authFail(state, action)
default:
return state
}
component.js
import React, { Component } from 'react'
import { connect } from 'react-redux'
import { auth } from './actions.js'
class MyComponent extends Component {
checkLogin(e){
e.preventDefault()
var username = e.target.elements.username.value
var password = e.target.elements.password.value
this.props.signIn(username, password)
}
render() {
let content = <div>Login succeed. User id is {this.props.userId}</div>
if (this.props.loading) {
content = <div>Loading...</div>
}
if (this.props.error) {
content = <div>Error: {this.props.error}</div>
}
return <React.Fragment>{content}</React.Fragment>
}
}
const mapStateToProps = state => {
return {
error: state.auth.error,
loading: state.auth.loading,
userId: state.auth.userId
}
}
const mapDispatchToProps = dispatch => {
return {
signIn: (username, password) => dispatch(auth(username, password))
}
}
export default connect(mapStateToProps, mapDispatchToProps)(MyComponent)

mapping / passing down redux actions to stateless component

After changing one of my components, (Profile.js) from a class to a function to simplify and have cleaner code, the onClick triggering of a redux action (like) no longer does anything.
Some have pointed out the action needs to be map differently, but I'm not sure why as I'm still new to redux and it's confusing as to why it works fine as a class but not as a function.
What adds to the confusion is that I'm also using react thunk to make things async.
User.js
import { fetchUser, like } from '../../actions/userActions';
class User extends React.Component {
componentDidMount() {
const { username } = this.props.match.params;
this.props.fetchUser(username);
}
render() {
const { like, user } = this.props;
return (
<Profile user={user} like={like} />
)
}
}
const mapStateToProps = state => ({
user: state.store.user
});
export default connect(mapStateToProps, {fetchUser, like})(User);
Profile.js Before
import { like, user } from '../../actions/userActions';
class Profile extends React.Component {
const { like, user } = this.props
return (
<a onClick={() => like(user.username)}>Like</a>
)
}
export default connect (mapStateToProps, {like}){Profile)
Profile.js After
const Profile = (props) => {
const { like, user } = props
return (
<a onClick={() => like(user.username)}>Like</a>
)
}
actions.js
const url = 'http://localhost:3001'
function handleErrors(response) {
if (!response.ok) {
throw Error(response.statusText);
}
return response;
}
export const like = (username) => dispatch => {
fetch(`${url}/like/${username}`, {credentials: 'include', method: 'post'})
.then(handleErrors)
.then(res => res.json())
.then(res =>
dispatch({
type: LIKE,
payload: res
})
)
.catch(error => console.error('Error:', error))
}
export const fetchUser = (username) => dispatch => {
fetch(`${url}/${username}`, {credentials: 'include'})
.then(handleErrors)
.then(res => res.json())
.then(res =>
dispatch({
type: FETCH_USER,
payload: res
})
)
.catch(error => console.error('Error:', error))
}
reducers.js
export default function(state = initialState, action) {
switch (action.type) {
case FETCH_USER:
return {
...state,
user: action.payload.user
};
case LIKE:
return {
...state,
user: {
...state.user,
meta: {
...state.user.meta,
like: action.payload.like
}
}
};
store.js
const initialState = {};
const middleware = [thunk];
const store = createStore(
rootReducer,
initialState,
compose(
applyMiddleware(...middleware),
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
)
);
export default store;
console.log of like in Profile.js
const Profile = (props) => {
const { user, like } = props
console.log(like)
ƒ like(username) {
return function (dispatch) {
fetch(url + '/like/' + username, { credentials: 'include', method: 'post' }).then(handleErrors).then(function (res) {
return res.json();
…
If I were to create a normal function such as
const test = () => { console.log('test') }
and change the onClick={} in Profile.js to use that, it works fine.
You should create handler in the User component, call your action creator there and pass it as a callback to child Profile component.
So, your code will looks like:
import { like } from '../../actions/userActions';
class User extends React.Component {
...
onClickHandler = username => {
return () => {
this.props.like(username);
}
}
render() {
const { user } = this.props;
return <Profile user={user} onClickHandler={this.onClickHandler} />
}
}
const mapStateToProps = state => ({
user: state.store.user
});
export default connect(mapStateToProps, {fetchUser, like})(User);
Then, call onClickHandler in your Profile component:
const Profile = props => {
const { onClickHandler, user } = props;
return (
<button onClick={onClickHandler(user.username)}>Like</button>
)
}
Hope it will helps.

React Redux Axios: POST Request not receiving credentials from redux state

I have been working on authentication with my project. I have a REST api backend that serves JWT tokens. My front end stack is ReactJS, Redux, Axios and Redux Thunk.
My question is why when I submit my form it does not send any credentials?
But when I console log the action and payload on credChange it seems to be correct. Am I not setting the state somewhere?
Also, axios does not catch the 400 Bad Request error.
Here is my code:
AuthActions.js
export const credChange = ({ prop, value }) => {
return {
type: CRED_CHANGE,
payload: { prop, value },
};
};
export const logoutUser = () => {
return (dispatch) => {
dispatch({ type: LOGOUT_USER });
};
};
const loginSuccess = (dispatch, response) => {
dispatch({
type: LOGIN_USER_SUCCESS,
payload: response.data.token,
});
};
const loginError = (dispatch, error) => {
dispatch({
type: LOGIN_USER_ERROR,
payload: error.response.data,
});
};
export const loginUser = ({ empNum, password }) => {
return (dispatch) => {
dispatch({ type: LOGIN_USER });
axios({
method: 'post',
url: 'http://127.0.0.1:8000/profiles_api/jwt/authTK/',
data: {
emp_number: empNum,
password,
},
})
.then(response => loginSuccess(dispatch, response))
.catch(error => loginError(dispatch, error));
};
};
AuthReducer.js
const INITIAL_STATE = {
empNum: '',
password: '',
empNumErr: null,
passwordErr: null,
authTK: null,
loading: false,
};
export default (state = INITIAL_STATE, action) => {
switch (action.type) {
case CRED_CHANGE:
return { ...state, [action.payload.prop]: action.payload.value };
case LOGIN_USER:
return {
...state,
...INITIAL_STATE,
loading: true,
};
case LOGOUT_USER:
return {
...state,
INITIAL_STATE,
};
case LOGIN_USER_SUCCESS:
return {
...state,
...INITIAL_STATE,
authTK: action.payload,
};
case LOGIN_USER_ERROR:
return {
...state,
...INITIAL_STATE,
empNumErr: action.payload.emp_number,
passwordErr: action.payload.password,
};
default:
return state;
}
};
LoginForm.js
import React, { Component } from 'react';
import { connect } from 'react-redux';
import {
credChange,
loginUser,
logoutUser,
} from '../Actions';
class LoginForm extends Component {
constructor() {
super();
this.onFormSubmit = this.onFormSubmit.bind(this);
this.renderEmpNumErr = this.renderEmpNumErr.bind(this);
this.empNumChange = this.empNumChange.bind(this);
this.passwordChange = this.passwordChange.bind(this);
}
onFormSubmit() {
const { empNum, password } = this.props;
this.props.loginUser({ empNum, password });
}
empNumChange(text) {
this.props.credChange({ prop: 'empNum', value: text.target.value });
}
passwordChange(text) {
this.props.credChange({ prop: 'password', value: text.target.value });
}
renderEmpNumErr() {
if (this.props.empNumErr) {
return (
<p>
{this.props.empNumErr}
</p>
);
}
return null;
}
render() {
return (
<div>
<form onSubmit={this.onFormSubmit}>
<label htmlFor="numberLabel">Employee Number</label>
<input
id="numberLabel"
type="password"
value={this.props.empNum}
onChange={this.empNumChange}
/>
<label htmlFor="passLabel">Password</label>
<input
id="passLabel"
type="password"
value={this.props.password}
onChange={this.passwordChange}
/>
<button type="submit">Login</button>
</form>
{this.renderEmpNumErr()}
</div>
);
}
}
const mapStateToProps = ({ counter }) => {
const {
empNum,
password,
loading,
empNumErr,
passwordErr,
authTK,
} = counter;
return {
empNum,
password,
loading,
empNumErr,
passwordErr,
authTK,
};
};
export default connect(mapStateToProps, { credChange, loginUser, logoutUser })(LoginForm);
After Submitting form with credentials
The console says:
POST XHR http://127.0.0.1:8000/profiles_api/jwt/authTK/ [HTTP/1.0 400 Bad Request 5ms]
And the POST request Raw Data is blank, therefore no credentials were sent.
{"emp_number":["This field is required."],"password":["This field is required."]}
EDIT
If there is any other information I can provide please say so but I think this should be sufficient.
Looks like empNum and password aren't getting set in the state. This is because the action object returned by credChange doesn't get dispatched, so the reducer never get called:
// dispatch calls the reducer which updates the state
dispatch(actionCreator())
// returns an action object, doesn't call reducer
actionCreator()
You can dispatch actions automatically by calling a bound action creator:
// calls the reducer, updates the state
const boundActionCreator = () => {dispatch(actionCreator())}
// call boundActionCreator in your component
boundActionCreator()
mapDispatchToProps can be used to define bound action creators (to be passed as props):
const mapDispatchToProps = (dispatch) => {
return {
credChange: ({ prop, value }) => {dispatch(credChange({prop, value})},
loginUser: ({ empNum, password }) => {dispatch(loginUser({empNum, password})},
logoutUser: () => {dispatch(logoutUser()},
}
}
export default connect(mapStateToProps, mapDispatchToProps)(LoginForm);
This should solve the state update issue, allowing props that read from state (empNumber, password, etc.) to update as well.

Resources