Redux : Getting null value after calling Reducer in React Native? - react-native

I'm making an API Call to get a value that i will store in my reducer. Although when i'm calling my reducer i'm getting null.
here is my code to get the value :
export function getValue(token) {
return fetch('URI', { method: 'GET'})
.then(response => response.json())
.then((response) => {
return response.value;
});
}
Then i have my redux :
const UPDATE_VALUE = 'user/UPDATE_VALUE';
...
const initialState = {
myValue: null,
};
export default function reducer(state = initialState, action = {}) {
switch (action.type) {
case UPDATE_VALUE:
return {
...state,
myValue: action.value
};
default:
return state;
}
}
export function updateValue(value) {
return {
type: UPDATE_VALUE,
value,
};
}
And here i call the api to stock the value. I'm getting the value and it existes but when i want to store and get it's value i'm getting null :
const getMyValue = new Promise((resolve) => {
return getMyValue(token).then((value) => {
updateValue(value === null ? null : value);
resolve();
});
});

Related

React Native how get data from asynchrone function

I try to get data from an asynchronestorage function
_retrieveData = async () => {
var test = await AsyncStorage.getItem('myitem')
return test
}
_generateRandomCards() {
console.log(this._retrieveData())
}
But that return :
Promise {
"_U": 0,
"_V": 0,
"_W": null,
"_X": null,
}
Edit : After the answer of Václav Ryska, i can change it with setstate, but that reload once if i call getValue from componentDidMount, and infinite loop in my generaterandomcards function.
My code :
componentDidMount() {
this.getValue()
}
getValue = async () => {
AsyncStorage.getItem('key')
.then(data => {
this.setState({deckDrawToday: true});
})
}
_generateRandomCards() {
console.log(this.state.deckDrawToday)
...
this._generateRandomCardsTrue()
...
return (
this._generateViewCards()
)
}
_generateRandomCardsTrue() {
...
}
_generateViewCards() {
...
}
render() {
return (
this._generateRandomCards()
)
}
return is not a valid statement for async functions, you gotta set the value in a callback to a variable
this.state = {
value: null
}
componentDidMount() {
this.getValue();
}
getValue = async () => {
AsyncStorage.getItem('key')
.then(data => {
this.setState({value: data});
console.log(data)
})
}
use console.log(await this._retrieveData()) since your function is async

React Redux rejectWithValue() not working

I'm currently facing a problem, when I try to reject a value when my node-fetch request fail, thunkApi.rejectWithValue() isn't working. However when my request is pending or when It's fulfilled, It's working fine.
Here's my slice :
export const userSlice = createSlice({
name: "user",
initialState: initialState as User,
reducers: {
...
},
extraReducers: (builder) => {
...
builder.addCase(changePassUser.pending, (state) => {
GGLog("FETCHING CHANGEPASS API...");
state.isFetching = true;
return state;
});
builder.addCase(changePassUser.fulfilled, (state, { payload }) => {
GGLog("FULFILLED CHANGEPASS:", JSON.stringify(payload));
state.isFetching = false;
state.isSuccess = true;
state.isError = false;
return state;
});
// eslint-disable-next-line #typescript-eslint/no-explicit-any
builder.addCase(changePassUser.rejected, (state, { payload }: any) => {
GGLog("REJECTED CHANGEPASS:", JSON.parse(payload));
state.isFetching = false;
state.isError = true;
state.errorMessage = payload.data;
return state;
});
},
});
Here's my thunk :
export const changePassUser = createAsyncThunk(
"users/password/update",
async ({ oldpassword, newpassword }: RegisterParameters, thunkAPI) => {
try {
const res = await changePassApi.changePass.return({
oldpassword: oldpassword,
newpassword: newpassword,
});
GGLog("API_CHANGEPASS_RES:", res);
const data = await res.json();
if (res.ok) {
GGLog("API_DATA_RESPONSE_OK: ", data);
const tokenData = JSON.stringify(res.headers);
const token = JSON.parse(tokenData).map["x-auth"];
await localStorage.store("token", token);
return data;
} else {
GGLog("API_DATA_RESPONSE_NOK: ", data);
return thunkAPI.rejectWithValue(data);
}
} catch (e) {
GGLog("Error while fetching Login API => ", e);
return thunkAPI.rejectWithValue(e);
}
}
);
And here's the result in the console :
Console output
Any ideas ? Am I missing something ?
Thanks :)
Okay I've found my problem, I was just focused on the thunk and didn't pay attention to the promise rejection. I was trying to parse a JSON that does'nt exist... Just remove the GGLog("REJECTED CHANGEPASS:", JSON.parse(payload));in the slice.
It's working fine now !

Cant get Auth token passed into reducer in redux

I have my userKey in the 'userLogin' function below, but when i get ready to send the userkey into my reducer, its not there.
I've tried updating my action to wrapping up the setUserId function into 'userLogin', but i keep getting null in my reducer (the actions are triggering, but its not making its way to the reducer. Help please!
action file
export const userLogin = userKey => {
return async dispatch => {
await AsyncStorage.setItem('userKey', userKey).then(userKey => {
console.log('userKey')
console.log(userKey) // have the key here
dispatch(setUserId(userKey))
})
}
}
export const setUserId = userKey => {
console.log('userKey')
console.log(userKey) // comes up as Null
return {
type: SET_USERID,
userKey: userKey
}
}
reducer file
import { SET_USERID, REMOVE_USERID } from '../actions/actionTypes'
const initialState = {
userKey: ''
};
const reducer = (state = initialState, action) => {
switch (action.type) {
case SET_USERID:
return {
...state,
userKey: action.userKey
};
case REMOVE_USERID:
return {
...state,
userKey: null
};
default:
return state;
}
};
export default reducer;
try this:
export const userLogin = userKey => {
return async dispatch => {
try {
await AsyncStorage.setItem('userKey', userKey)
console.log('userKey')
console.log(userKey) // have the key here
dispatch(setUserId(userKey))
} catch (ex) {
console.log(ex);
}
}
}

React native axios call throws 403 but postman correctly outputs the data

I'm working on a RN app, which has redux in it. Now I can login with the help of jwt but when Im trying the to get the data from my other component its giving me 403 error. Please find below the relevant code.
Here is my reducer:
const initState = {
isLoadingCollegeDashList : false,
collegeDashList:{},
collegeDashListFail:false
}
const collegeReducer = ( state = initState, action) => {
switch(action.type){
case 'IS_LOADING_COLLEGE_DASH_LIST' :
return{
...state,
isLoadingCollegeDashList: true,
collegeDashList : false
}
case 'COLLEGE_DASH_LIST' :
return {
...state,
isLoadingCollegeDashList : false,
collegeDashList : true,
userData : action.userData
}
case 'COLLEGE_DASH_LIST_FAIL' :
return{
...state,
isLoadingCollegeDashList:false,
collegeDashList: false,
collegeDashListFail: action.error
}
default :
return state
}
}
and here's my action that's making get request
export const populateCollege = (token) => {
const headers = {
'api-secret' : ...secret...,
'authorization':...authToken...,
'Content-Type': 'application/json',
}
return dispatch => {
dispatch(isLoadingCollegeDashList(true));
return axios.get( '...api/api/...', {
},{
headers:headers,
})
.then((response) => {
if(response.status < 300){
dispatch(isLoadingCollegeDashList(false))
dispatch(collegeDashList(response))
console.log(response);
}
else{
response.json().then((responseJSON) => {
console.log("responseJSON",responseJSON);
dispatch(isLoadingCollegeDashList(false))
dispatch(collegeDashListFail(responseJSON.message))
})
}
})
.catch((error) => {
console.log("error",error);
dispatch(isLoadingCollegeDashList(false))
dispatch(collegeDashListFail(error))
})
}
}
export const isLoadingCollegeDashList = (bool) => {
return{
type:'IS_LOADING_COLLEGE_DASH_LIST',
isLoadingCollegeDashList:bool
}
}
export const collegeDashList = (userData) => {
return{
type:'COLLEGE_DASH_LIST',
userData
}
}
export const collegeDashListFail = (error) => {
return{
type:'COLLEGE_DASH_LIST_FAIL',
error
}
}
here's action that im calling if you want to check it
const mapDispatchToProps = dispatch => ({
populateCollege : (token) => dispatch(actions.populateCollege({token}))
});
PS I've for now stored token in the state of one hence passing the token from this dispatch itself.
Let me know if you need any clarification / more information then do let me know. Thanks in advance
Make sure you have the authorisation schema before your token. The schema can be like Basic, Bearer or any other value based on your authorisation details. (eg. Authorization: Bearer TOKEN).
Also, try to reuse your auth headers while creating the axios instance so you won't need to inject them on every call.

Redux action returns undefined?

Redux store get undefined in action.data, even though my reducer function gets the correct result from the api, my dispatch is in the correct place.
My Reducer function:
const convertPosition = StateHelper.createAsyncOperation(MODULE, 'convertPosition');
export function $convertPosition(lat, long) {
return (dispatch) => {
dispatch(Activity.$processing(MODULE, $convertPosition.name));
dispatch(convertPosition.request());
return fetch(`${API_ENDPOINT}/shared/maps/address?latlong=${lat},${long}`, {
headers: {
Authorization: `Bearer ${AuthService.getAccessToken()}`,
},
})
.then(FetchHelper.ResponseHandler, FetchHelper.ErrorHandler)
.then((result) => dispatch(convertPosition.success(result)))
.catch((error) => dispatch(convertPosition.failure(error)))
.finally(() => dispatch(Activity.$done(MODULE, $convertPosition.name)));
};
}
My Reducer statement:
case convertPosition.SUCCESS:
return {
...state,
locationName: action.data,
};
case convertPosition.FAILURE:
return {
...state,
locationName: null,
};
After I checked the API with postman, the result was an array so the code was:
...
.then((result) => dispatch(convertPosition.success({result: result})))
....