How to persist Login with token? - javascript

Hello there I have created dotnet core web api for login and register but in the app after refresh it always tries to log in again. Since I am new to react native I could not apply solutions to my project. I use redux and here is my action :
export const signin = (email, password) => {
return async dispatch => {
const response = await fetch(
'http://localhost:5000/api/user/login',
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
email: email,
password: password,
}),
}
);
if (!response.ok) {
throw new Error('Something went wrong!');
}
const resData = await response.json();
console.log(resData);
dispatch({ type: SINGIN, token: resData.token, userId: resData.id });
saveDataToStorage(resData.token);
};
};
const saveDataToStorage = (token, userId) => {
AsyncStorage.setItem('userData', JSON.stringify({
token: token,
})
);
};
And here is my navigator with react navigation 5 :
export const Navigator = () => {
const [userToken, setUserToken] = React.useState(null);
const userData = AsyncStorage.getItem('userData');
const authContext = React.useMemo(() => {
return {
signIn: () => {
setUserToken(userData);
},
singnUp: () => {
setUserToken(userData);
},
signOut: () => {
setUserToken(null);
},
};
}, [userData]);
return (
<AuthContext.Provider value={authContext}>
<NavigationContainer>
<RootStackScreen userToken={userToken} />
</NavigationContainer>
</AuthContext.Provider >
);
};
As I said I could not find a way to apply solutions that I found. Thank you for you help.

First, make sure all of your actions with AsyncStorage should be async(Use promise or async/await).
Then follow this to implement the authentication flow of your application.
https://reactnavigation.org/docs/auth-flow
My this answer will be helpful for you.
React Navigation 5 Auth Flow

Related

TypeError: Cannot read properties of undefined (reading 'protocol') in React using Axios

So basically as the APP.js renders it is not sending requests to the backend. I am calling the currentUser function inside App.js function. Please help me I am stuck
app.js file
useEffect(() => {
const unsubscribe = auth.onAuthStateChanged(async (user) => {
if (user) {
const getidtoken = await user.getIdTokenResult();
currentUser(getidtoken.token)`enter code here`
.then((res) => {
console.log(res);
dispatch({
type: 'LOGGED_IN_USER',
payload: {
email: res.data.email,
name: res.data.name,
role: res.data.role,
_id: res.data._id,
},
});
})
.catch((err) => {
console.log(err);
});
}
});
currentuser.js Function
export const currentUser = async (authtoken) => {
return await axios.post(
process.env.REACT_APP_API_USER,
{},
{ headers: { authtoken: authtoken } }
);
};
enter image description here

How to access getTokenSilently() auth0 in RTK Query?

I'm completely new to using RTK Query, I created the app before but without the authentication and everything worked, now I want to add the authentication using Auth0 but I can't access any file I add getTokenSilently()
PS. getTokenSilently is the {token}
thanks for help
export const myApi = createApi({
reducerPath: "points",
baseQuery: fetchBaseQuery({
baseUrl: "/",
prepareHeaders: (headers, { getState }) => {
const token = getState()
if (token) {
headers.Authorization = `Bearer ${token}`
}
return headers
},
}),
endpoints: builder => ({
getPoints: builder.query({
query: () => `/`,
}),
}),
})
export const { useGetPointsQuery } = myApi
What I ended up doing was to store the token in my state and then added this to App:
useEffect(() => {
(async () => {
try {
const token = await getAccessTokenSilently({})
dispatch(setToken(token))
} catch (e) {
console.error(e);
}
})()
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [getAccessTokenSilently])
There is a little more logic to know if you have not yet authenticated so that you can render a pending authentication state, but this was enough to get me going.

Nodejs MongoDB - add new entry Post()

so trying to post new entry into MongoDB. but getting this error in Redux Product validation failed: name: Path 'name' is required., description: Path 'description' is required.
nodejs version: 14.9.0
and Atlas mongodb.
frontEnd addProduct.js page:
import { createProduct } from '../redux/actions/productActions'
const [name, setName] = useState('')
const [description, setDescription] = useState('')
const createProductHandler = (e) => {
e.preventDefault()
dispatch(createProduct({
name,
description
}))
}
const nameHandler = (e) => {
setName(e.target.value)
}
const descriptionHandler = (e) => {
setDescription(e.target.value)
}
return (
<input type='text' onChange={nameHandler} />
<input type='text' onChange={descriptionHandler} />
<input type="submit" value='submit' onClick={createProductHandler} />
)
productController:
const createdProduct = asyncHandler(async (req, res) => {
const mongoProduct = async (data) => {
return new Product({
name: data.name,
description: data.description
})
}
const product = await mongoProduct(req.body)
const createdProduct = await product.save()
res.status(201).json(createdProduct)
})
productActions:
export const createProduct = () => async (dispatch, getState) => {
try {
dispatch({
type: 'PRODUCT_CREATE_REQUEST',
})
const {
userLogin: {userInfo},
} = getState()
const config = {
headers: {
Authorization: `Bearer ${userInfo.token}`,
},
}
const { data } = await axios.post(`/api/products`, {}, config)
dispatch({
type: 'PRODUCT_CREATE_SUCCESS',
payload: data
})
} catch (error) {
dispatch({
type: 'PRODUCT_CREATE_FAIL',
payload:
error.response && error.response.data.message
? error.response.data.message
: error.meessage,
})
}
}
productReducers.js:
export const productCreateReducer = (state = {}, action) => {
switch (action.type) {
case 'PRODUCT_CREATE_REQUEST':
return {loading: true}
case 'PRODUCT_CREATE_SUCCESS':
return {loading: false, success: true, product: action.payload}
case 'PRODUCT_CREATE_FAIL':
return {loading: false, error: action.payload}
default:
return state
}
}
alternatively when i try to populate the database from post-man using this code in productController.js it works fine with sample data:
const createdProduct = asyncHandler(async (req, res) => {
const product = new Product({
name: 'Sample Name',
description: 'Sample Description'
})
const createdProduct = await product.save()
res.status(201).json(createdProduct)
})
plus im getting POST ipadress/api/products 500 (Internal Server Error) in console
You can config your axios api service config to separate file and use axios
const request = axios.create({
// baseURL: 'https://mock-api.com',
baseURL: BASE_URL ,
timeout: 5000
})
request.interceptors.request.use(
config => {
// get token
if (// check your token) {
config.headers["Authorization"] = "Bearer ${your-token}"
}
return config
},
error => {
// Do something with request error
console.log(error) // for debug
Promise.reject(error)
}
)
// Can also config axios response interceptors to handle API error
Your redux action
import axiosInstance from './your-axios-config-path'
export const createProduct = (product) => async (dispatch, _getState) => {
try {
dispatch({ type: 'PRODUCT_CREATE_REQUEST' })
const response = await axiosInstance.post(`/api/products`, {...product})
dispatch({
type: 'PRODUCT_CREATE_SUCCESS',
payload: response?.data ?? {}
})
} catch (error) {
dispatch({
type: 'PRODUCT_CREATE_FAIL',
payload: // error message,
})
}
}
Alternatively, you can use Redux Toolkit, It much easier to setup store and using. It includes createAsyncThunk, RTK Query to handle side effect.

React Redux problem on dispatching on button

I have a button that dispatches an action to create a post, for some reason the request never proceeds and it fails. This is the action. I have constants that's why types is not on a string
export const createPost = () => async (dispatch, getState) => {
try {
dispatch({
type: POST_CREATE_REQUEST,
});
const {
userLogin: { userInfo },
} = getState();
const config = {
headers: {
Authorization: `Bearer ${userInfo.token}`,
},
};
const { data } = await axios.post(
`http://localhost:5000/api/posts`,
config
);
dispatch({
type: POST_CREATE_SUCCESS,
payload: data,
});
} catch (error) {
const message =
error.response && error.response.data.message
? error.response.data.message
: error.message;
// if (message === 'Not authorized, token failed') {
// dispatch(logout());
// }
dispatch({
type: POST_CREATE_FAIL,
payload: message,
});
}
};
It continues to the POST_CREATE_REQUEST but always errors out to the POST_CREATE_FAIL.
I tried using postman and it works fine, I think the problem is the createPost action can't seem to receive the token even though im logged in as an admin, I'm not sure.
This is the useSelector of the postCreate
const postCreate = useSelector(state => state.postCreate);
const {
loading: loadingCreate,
error: errorCreate,
success: successCreate,
post: createdPost,
} = postCreate;
and this is the useSelector of the user that is logged in, currently as an admin.
const userLogin = useSelector(state => state.userLogin);
const { userInfo } = userLogin;
Rewrite this code
const { data } = await axios.post(
`http://localhost:5000/api/posts`,
config
);
as
const res = await axios.post(
`http://localhost:5000/api/posts`,
config
);
const data = res && res.data
There is already values on my Controller at the backend and just needed to add brackets in the action
from this
const { data } = await axios.post(
`http://localhost:5000/api/posts`,
config
);
to this
const { data } = await axios.post(
`http://localhost:5000/api/posts`, {},
config
);

How to set response of an api on submit using redux in react js.?

I'm trying to send an response to the api on submit but the problem I'm having is that when ever i hit submit button my paymentMethod parameter is somehow not going through in the api. below I'm posting my submit button and my action. other than that I'm also getting this error.
submit
submitPaypal = () => {
const { frequencyPaypal, paymentMethod } = this.state;
this.setState({
paymentMethod: "Paypal",
});
this.props.setPaymentOption({
frequencyPaypal,
paymentMethod,
});
};
Action/payment.js
export const setPaymentOption = (userdata) => {
return async (dispatch) => {
dispatch(fullScreenLoader(true));
let token = await getToken();
const api = new Axios();
const response = await api.post(
SET_PAYMENT_OPTION,
{
paymentOption: userdata.paymentOption,
paypalPaymentOption: userdata.paypalPaymentOption,
trustlyPaymentOption: userdata.trustlyPaymentOption,
payoutReferenceId: userdata.payoutReferenceId,
varation_id: userdata.varation_id,
},
{
Authorization: `Bearer ${token}`,
},
API_URL2
);
const { data } = response;
console.log(userdata)
dispatch(fullScreenLoader(false));
dispatch({
type: SET_PAYMENT,
payload: data,
});
};
};
reducer
case SET_PAYMENT:
return {
...state,
paymentGateway: action.payload,
};
map state to props
const mapStateToProps = (data) => ({
webSercvices: data.payments.webServices,
paymentGate: data.payments.paymentGateway,
payByPaypal: data.payments.payByPaypal,
user: data.authenticateUser.user,
isAuthenticated: data.authUser,
});
const mapDispatchToProps = (dispatch) =>
bindActionCreators(
{
getPaymentWebServiceApi,
alertPopUp,
setPaymentOption,
savePaypal,
authenticateUser,
},
dispatch
);
ISSUE
on submit you are sending frequencyPaypal and paymentMethod in setPaymentOption action and there you are accessing many properties which is undefined there like paymentOption and more...
SUGGESTION
In (Action/payment.js)
const response = await api.post(
SET_PAYMENT_OPTION,
{
paymentOption: userdata.paymentOption, // this is undefined
paymentOption: userdata.frequencyPaypal, // this is valid
paymentOption: userdata.paymentMethod, // this is valid
paypalPaymentOption: userdata.paypalPaymentOption, // this is undefined
trustlyPaymentOption: userdata.trustlyPaymentOption, // this is undefined
payoutReferenceId: userdata.payoutReferenceId, // this is undefined
varation_id: userdata.varation_id, // this is undefined
},
{
Authorization: `Bearer ${token}`,
},
API_URL2
);

Categories

Resources