React Redux reducer not returning - react-native

I have an application that has to return only future events. I am able to parse through my firebase realtime db and return only future events in my action. It then passes this array of data to my reducer. In my reducer, I am logging the payload. The console log displays the data I want. Now in my component screen, I console log to see what data I should see from the reducer and it is empty.
My action:
export const getAllEvents = () => {
var currentTime = Date.now();
return (dispatch) => {
var ref = firebase.database().ref('Events/');
ref.orderByChild("availableSpots").on("value", function(snapshot) {
snapshot.forEach(child => {
var time = child.val().epochTime;
if (currentTime < time) {
console.log("Events redux: ", child.val());
dispatch({ type: GET_EVENT_LIST, payload: child.val() });
}
})
});
});
}
}
As you can see I am console logging the child.val() which comes out as expected below:
Now I have this hooked up to my reducer via dispatch.
import { GET_EVENT_LIST } from '../actions/types';
const INITIAL_STATE = {
eventList: [],
};
const eventListReducer = (state = INITIAL_STATE, action) => {
switch (action.type){
case GET_EVENT_LIST:
console.log("action count", action.payload);
return { ...state, eventList: [...state.eventList, action.payload] };
default:
console.log("default ");
return state;
}
};
export default eventListReducer;
As you can see the console log of the action.payload is being logged and produces an expected result:
Now back in my component screen:
import { getUserThunk, getAllEvents } from '../actions';
import {connect} from 'react-redux';
class Home extends Component {
componentWillMount() {
console.log("Component will mount");
this.props.getUserThunk();
this.props.getAllEvents();
}
render() {
console.log("usersadf ", this.props.userReducer)
console.log("Props in home ", this.props.eventListReducer)
return (
//some return code here
);
}
export default connect(
state=>({userReducer: state.userReducer, eventListReducer: state.eventListReducer}),
{ getUserThunk, getAllEvents }
)(Home);
Now as you can see I do have different redux action and reducer hooked up and it comes through. However, the one in question returns empty.

Related

vuex unknown action type: login

Login.vue
<script setup>
import { useLayout } from '#/layout/composables/layout';
import { ref, computed } from 'vue';
import AppConfig from '#/layout/AppConfig.vue';
import { decodeCredential } from 'vue3-google-login'
import {auth} from '../../../store/modules/auth.module';
import { useStore } from "vuex";
const store = useStore()
const { layoutConfig, contextPath } = useLayout();
const email = ref('');
const password = ref('');
const checked = ref(false);
const logoUrl = computed(() => {
return `${contextPath}layout/images/${layoutConfig.darkTheme.value ? 'logo-white' : 'logo-dark'}.svg`;
});
const callback = (response) => {
const userData = decodeCredential(response.credential);
// const authStore = auth;
// console.log(authStore.login());
if (userData.email=='****#gmail.com') {
return store.dispatch('login')
}
}
</script>
auth.module.js
import AuthService from "../../services/auth.service";
const user = JSON.parse(localStorage.getItem('token'));
const initialState = user
? { status: { loggedIn: true }, user }
: { status: { loggedIn: false }, user: null };
export const auth = {
namespaced: true,
state: initialState,
actions: {
login({ commit }, user) {
return AuthService.login(user).then(
user => {
commit('loginSuccess', user);
return Promise.resolve(user);
},
error => {
commit('loginFailure');
return Promise.reject(error);
}
);
},
logout({ commit }) {
AuthService.logout();
commit('logout');
},
},
mutations: {
loginSuccess(state, user) {
state.status.loggedIn = true;
state.user = user;
},
loginFailure(state) {
state.status.loggedIn = false;
state.user = null;
},
logout(state) {
state.status.loggedIn = false;
state.user = null;
},
}
};
auth.service.js
import axios from 'axios';
const API_URL = 'http://localhostGetToken';
class AuthService {
async login(user) {
const response = await axios
.post(API_URL, {
username: user.username='admin',
password: user.password='password'
});
if (response.data.accessToken) {
localStorage.setItem('token', JSON.stringify(response.token));
}
console.log(response);
return response.data;
}
async logout() {
localStorage.removeItem('token');
}
}
export default new AuthService();
Here i trying to login if email true to trigger login vuex.but i get a error [vuex] unknown action type: login
how to solve this?
You haven't included in your question how the auth store is linked to your application.
I'm guessing you have a main store and the auth store is one of its modules.
If my guess is true, you should dispatch auth/login, not login, since the main store doesn't have a login action.
Side note: I suggest you carefully read How to Ask, to improve the quality of your future questions.
The problems with your current question:
you posted too much irrelevant code and, at the same time, you haven't posted all the relevant code. You should have included:
a) the action deemed unknown (everything else in that store is irrelevant for this question)
b) how the store is linked to the app (main store + how the store is instantiated in the app) - these bits are missing
c) how you're consuming the action in the component (everything else in the component is irrelevant for the question)
you started with the code. Always start by explaining the problem, so when people look at the code, they know what to look for (and skip the irrelevant parts). This is also helpful for future users with a similar problem: they'll be able to quickly understand if your question is relevant for their problem.
The more users find the question useful, the more chances for it to get upvoted.
Another side-note: the condition used to dispatch is, most likely, wrong. It is only true when the email is actually '****#gmail.com'.
You should probably use if (userData.email.endsWith('#gmail.com')).

observable and computed not being reflected in a functional component

I am learning mobx for react-native and not able to see changes to done to observables or computed.
Basically, I want to listen to changes to observable from the component.
My store is simple:
import { observable, action, computed } from 'mobx';
import AsyncStorage from '#react-native-async-storage/async-storage';
class ConfigStore {
rootStore = undefined;
#observable activeConfig = {group: 'starter', TC: false};
constructor(rootStore) {
this.rootStore = rootStore;
}
#computed get termsLoaded(){
return this.activeConfig.TC;
}
#action async loadPreviousConfig() {
const configDetails = { group: 'starter', TC: false};
try {
const response = await AsyncStorage.multiGet([
'group',
'TC'
]);
configDetails.group = response[0][1] || 'starter';
configDetails.TC = response[1][1] === undefined ? false : true;
console.log(configDetails);// shows correct previously saved config
this.activeConfig = configDetails;
} catch (error) {}
}
}
export default ConfigStore;
From my component, I want to load first previous configuration settings and have them reflect in my app. Basically, I want to check the value of TC ater calling loadPreviousConfig, they return false still:
import { inject, observer } from 'mobx-react';
const ConfigComponent = (props) => {
const { store } = props;
const { termsLoaded, activeConfig, loadPreviousConfig } = store.configStore;
useEffect(() => {
const init = async () => {
await loadPreviousConfig();
console.log(termsLoaded); //always false even though console from the store shows it is true.
};
init();
}, []); //tried [props]
return (
<View>
<Text>{activeConfig.group}</Text> //never changes
</View>
);
};
export default inject('store')(observer(ConfigComponent));

TypeError: undefined is not an object (evaluating '_UserInfoRedux.UserInfoActions.userInfoRequest')

I'm new to React Native, and I'm using Redux-Saga. Unfortunately, there is an error that I am unable to resolve.
I get this error when I dispatch an action:
TypeError: undefined is not an object (evaluating
'_UserInfoRedux.UserInfoActions.userInfoRequest')
Here's my Component wherein I dispatch the action:
import React, { Component } from 'react'
import { connect } from 'react-redux'
import {UserInfoActions } from '../Redux/UserInfoRedux'
class LoginScreen extends Component {
constructor(props){
super(props)
this.state = {
username: '', password: '', rememberPwd:false
}
this.props.getUserInfo();
}
componentWillReceiveProps(newProps) {
this.forceUpdate();
if (newProps.userInfo.error === null && newProps.userInfo.payload !== null) {
console.log(newProps.userInfo.payload.results);
} else {
console.log(">> error");
}
}
render() {
.
.
.
}
}
const mapStateToProps = state => {
return {
userInfo: state.userInfo,
};
};
const mapDispatchToProps = dispatch => {
return {
getUserInfo: () => {
console.log('clicked');
dispatch(UserInfoActions.userInfoRequest())
}
};
};
export default connect(
mapStateToProps,
mapDispatchToProps
)(LoginScreen);
Here's my redux class
import { createReducer, createActions } from 'reduxsauce'
import Immutable from 'seamless-immutable'
/* ------------- Types and Action Creators ------------- */
const { Types, Creators } = createActions({
userInfoRequest: ['data'],
userInfoSuccess: ['payload'],
userInfoFailure: null
})
export const UserInfoTypes = Types
export default Creators
/* ------------- Initial State ------------- */
export const INITIAL_STATE = Immutable({
data: null,
fetching: null,
payload: null,
error: null
})
/* ------------- Selectors ------------- */
export const UserInfoSelectors = {
getData: state => state.data
}
/* ------------- Reducers ------------- */
// request the data from an api
export const request = (state, { data }) =>
state.merge({ fetching: true, data, payload: null })
// successful api lookup
export const success = (state, action) => {
const { payload } = action
return state.merge({ fetching: false, error: null, payload })
}
// Something went wrong somewhere.
export const failure = state =>
state.merge({ fetching: false, error: true, payload: null })
/* ------------- Hookup Reducers To Types ------------- */
export const reducer = createReducer(INITIAL_STATE, {
[Types.USER_INFO_REQUEST]: request,
[Types.USER_INFO_SUCCESS]: success,
[Types.USER_INFO_FAILURE]: failure
})
And finally my Saga class
/* ***********************************************************
* A short word on how to use this automagically generated file.
* We're often asked in the ignite gitter channel how to connect
* to a to a third party api, so we thought we'd demonstrate - but
* you should know you can use sagas for other flow control too.
*
* Other points:
* - You'll need to add this saga to sagas/index.js
* - This template uses the api declared in sagas/index.js, so
* you'll need to define a constant in that file.
*************************************************************/
import { call, put } from 'redux-saga/effects'
import {UserInfoActions} from '../Redux/UserInfoRedux'
export function * getUserInfo (api, action) {
const { data } = action
// get current data from Store
// const currentData = yield select(UserInfoSelectors.getData)
// make the call to the api
const response = yield call(api.getUserInfo, data)
// success?
if (response.ok) {
// You might need to change the response here - do this with a 'transform',
// located in ../Transforms/. Otherwise, just pass the data back from the api.
yield put(UserInfoActions.userInfoSuccess(response.data))
} else {
yield put(UserInfoActions.userInfoFailure())
}
}
Thank you in advance for your help!
It's my own stupid mistake! Didn't know the importance of {} when importing. Removed {} in one of my imports and it's working now.
In my case I was assigning a variable to a hook call, but I didn't return anything inside that hook call, so my variable would not receive any value, hence the undefined value.
It is simple: if you are receiving undefined value, then this means your variable has no value, which is not what you may expect.
Try to debug your code to see where the error is coming from and why it is not giving the desired output.
Remember: undefined means no value.

Error: Actions must be plain objects. Use custom middleware for async actions. (React Native)

I am trying to make it so that if an item called code is not set in state with redux, it is called from AsyncStorage and state is set.
import {AsyncStorage} from 'react-native'
import { connect } from 'react-redux';
import {bindActionCreators} from 'redux'
import {handlePhoneNumber, saveCode} from './../../actions/RegistrationActions';
class EnterPhoneNumberScreen extends React.Component {
componentDidMount() {
let code = this.props.registration.code;
console.log("code is", code);
if(code){
// Do nothing
}else{
console.log("in the else");
this.props.getAndSetCode();
}
}
}
const getAndSetCode = () => dispatch => {
console.log("in get and set Code");
AsyncStorage.getItem('code')
.then((data) => {
console.log("data is ", data);
dispatch(saveCode(data));
console.log("in getAndSetCode method, Code is ", data);
})
}
const mapDispatchToProps = dispatch => (
bindActionCreators({
handlePhoneNumber,
getAndSetCode: () => dispatch(getAndSetCode()),
}, dispatch)
);
export default connect(mapStateToProps, mapDispatchToProps)(EnterPhoneNumberScreen);
The console outputs the following:
LOG code is null
LOG in the else
LOG in get and set Code
LOG data is 3tgvgq
LOG in getAndSetCode method, Code is 3tgvgq
I know thunk is properly installed because it is running elsewhere in the application. saveCode is just a normal action:
export const saveCode = code => ({
type: "SAVE_CODE",
payload: code
})
And this error appears in the iphone11 simulator:
How do I fix this?

How to update state in reducer

I have a problem with my reducer. I am using redux to create a login page. I have successfully logged in yet I failed to navigate to the next page. The state in my reducer is not updated. How do I solve this?
This is how I wrote my reducer:
import { LOGIN_SUCCESS } from '../actions/types';
const INITIAL_STATE={
isLoginSuccess:false,
}
export default function (state=INITIAL_STATE, action){
switch(action.type){
case LOGIN_SUCCESS:
return {
isLoginSuccess : true
}
default:
return INITIAL_STATE;
}
}
This is how I wrote my action:
import axios from 'axios';
import * as helper from '../common';
import { LOGIN_SUCCESS } from './types';
export const attemptLogin = (username, password) => async dispatch => {
let param = {
txtNomatrik: username,
txtPwd: password,
public_key: helper.PUBLIC_KEY,
secret_key: helper.SECRET_KEY
}
console.log(`${helper.ROOT_API_URL}/v1/basic/ad/std/login`)
let login_res = await
axios.post(`${helper.ROOT_API_URL}/v1/basic/ad/std/login`, param)
console.log(login_res.data);
if (login_res.data.status == 'Successful Login') {
const { login } = login_res.data;
await AsyncStorage.seItem('Login_token', username);
await AsyncStorage.setItem('profile', JSON.stringify(login));
dispatch({ type: LOGIN_SUCCESS, payload: { isLoginSuccess : true } });
}
}
I want to use the isLoginSuccess in my index file to navigate login to the next page like this:
componentWillReceiveProps(nextProps){
if(nextProps.isLoginSuccess){
this.props.navigation.navigate('logged');
}
}
Below is how I connect redux:
const mapStateToProps = ({ auth }) => {
return {
isLoginSuccess: auth.isLoginSuccess
}
}
export default connect(mapStateToProps, actions)(LoginScreen);
Below is my combineReducer file:
import {combineReducers} from 'redux';
import news from './welcome_reducer';
import auth from './login_reducer';
export default combineReducers({
news,
auth
})
How do I solve this? I feel lost now, have tried a lot of ways to solve it . The Api call for login is successful but the action is not dispatched at all. I can't update the state and I can't navigate to the next page. Please help me