React Naitve Redux getState Undefined - react-native

I am trying to Firebase Phone Authentication with React-redux. but i am getting getState undefined in Action file.
i am getting "confirmResult.confirm is undefined"
Action.Js
const onCodeDispatched = (code) => {
return (dispatch, getState) => {
console.log(getState())
getState().auth.confirmResult.confirm(code)
.then(user => onLoginSuccess(dispatch, user))
.catch(error => onCodeConfirmError(dispatch, error));
}
}
App.js
import React from 'react'
import {Provider} from 'react-redux'
import {createStore, applyMiddleware, compose} from 'redux'
import thunkMiddleware from 'redux-thunk'
import reducers from '../reducers'
import App from './App'
import {persistStore} from 'redux-persist'
import {PersistGate} from 'redux-persist/es/integration/react'
const middleware = [thunkMiddleware]
const store = compose(applyMiddleware(...middleware))(createStore)(reducers)
console.log(store)
let persistor = persistStore(store)
class Root extends React.PureComponent {
render() {
return (
<Provider store={store}>
<PersistGate persistor={persistor}>
<App />
</PersistGate>
</Provider>
)
}
}
export default Root
i am new in react-redux it is very confusing me i already read many articles i already spent many days finding the error can you please give me some idea why getState is returning Undefined.

Try to split how are you constructing the store. You can begin creating just a simple instance of store, like this:
const store = createStore(reducers, yourInitialState)
Then print the store and see what happened. If everything is okay, try to use compose, applyMiddleware, and thunk like that:
const store = createStore(
reducer,
compose(
applyMiddleware(thunk),
DevTools.instrument() // this is a really helpful instrument
)
)
If you have doubts just ask or follow the official doc from Redux website

Related

Redux: mapStateToProps is not being called

I understand this kind of question was already asked several times here at StackOverflow. But I tried all the recommended solutions and nothing works for me. I'm running out of ideas.
The problem is with a React Native application for Android. Basically, the app provides a search bar to search an underlying database. The search results should be put into the store.
I use Redux v4.0.5, React-Redux v7.1.3, React v16.12.0 and React Native v0.61.5. For debugging, I use React Native Debugger in the latest version.
Now the simplified code. First, the component with the search bar. Here, mapStateToProps() is called. User makes an input and useEffect() immediately runs the database query, which should result in immediately calling mapStateToProps().
import React, {useEffect, useRef, useState} from 'react';
import {connect} from 'react-redux';
import {RootState} from '../../../rootReducer/rootReducer';
import {setResultValueSearchBar} from '../../../store/searchBar/actions';
imports ...
type Props = {};
const SearchBar: React.FC<Props> = () => {
const [returnValue, setReturnValue] = useState('');
const [inputValue, setInputValue] = useState('');
useEffect(() => {
// get query results
// logic to finally get a result string that should be put into the store
const resultNames: string = resultNamesArray.toString();
// method to set local and Redux state
const sendReturnValueToReduxStore = (resultNames: string) => {
setReturnValue(resultNames);
setResultValueSearchBar({resultValue: resultNames});
console.log('result value sent to store ', resultNames);
};
// call above method
sendReturnValueToReduxStore(resultNames);
}, [inputValue, returnValue]);
return (
<View>
<ScrollView>
<Header searchBar>
<Item>
<Input
placeholder="Search"
onChangeText={text => setInputValue(text)}
value={inputValue}
/>
</Item>
</Header>
</ScrollView>
</View>
);
};
function mapStateToProps(state: RootState) {
console.log("map state to props!", state); // is only called one time, initially
return {
resultValue: state.searchBarResult.resultValue,
};
}
const mapDispatchToProps = {
setResultValueSearchBar,
};
export default connect(mapStateToProps, mapDispatchToProps)(SearchBar);
Here is the rootReducer:
import {combineReducers} from 'redux';
import searchBarResultReducer from '../store/searchBar/reducers';
import reducer2 from '../store/reducer2example/reducers';
const rootReducer = combineReducers({
searchBarResult: searchBarResultReducer,
reducer2Result: reducer2,
});
export type RootState = ReturnType<typeof rootReducer>;
Here is the searchBarResultReducer in reducers.ts file:
import {
SearchBarResultState,
SET_RESULT_VALUE_SEARCHBAR,
ResultValueType,
} from './types';
const initialState: SearchBarResultState = {
resultValue: 'No results',
};
// take state and action and then return a new state
function searchBarResultReducer(
state = initialState,
action: ResultValueType,
): SearchBarResultState {
console.log('invoked result: ', action.type); // called only initially
if (action.type === 'SET_RESULT_VALUE_SEARCHBAR') {
return {
...state,
...action.payload,
};
} else {
return state;
}
}
export default searchBarResultReducer;
And the corresponding types.ts ...
export const SET_RESULT_VALUE_SEARCHBAR = 'SET_RESULT_VALUE_SEARCHBAR';
export interface SearchBarResultState {
resultValue: string;
}
interface ResultValueAction {
type: typeof SET_RESULT_VALUE_SEARCHBAR;
payload: SearchBarResultState;
}
export type ResultValueType = ResultValueAction
... and the actions.ts:
import {SET_RESULT_VALUE_SEARCHBAR, ResultValueType, SearchBarResultState} from './types'
export const setResultValueSearchBar = (resultValue: SearchBarResultState): ResultValueType => ({
type: SET_RESULT_VALUE_SEARCHBAR,
payload: resultValue,
});
And index.js:
import React from 'react';
import {AppRegistry} from 'react-native';
import {createStore, applyMiddleware, compose} from 'redux';
import {Provider} from 'react-redux';
import App from './App';
import {name as appName} from './app.json';
import rootReducer from './src/rootReducer/rootReducer';
import Realm from 'realm';
import { composeWithDevTools } from 'redux-devtools-extension';
import invariant from 'redux-immutable-state-invariant';
const composeEnhancers = composeWithDevTools({});
const store = createStore(
rootReducer,
composeEnhancers(applyMiddleware(invariant()))
);
const Root = () => {
Realm.copyBundledRealmFiles();
return (
<Provider store={store}>
<App />
</Provider>
);
};
AppRegistry.registerComponent(appName, () => Root);
To summarize: Whenever the database query succeeds, the result value should be sent to the store. But in the React Native Debugger/Redux Devtools, the reducer/mapStateToProps() is called only once and only, as shown by the console.log s in the code.
What is going on here?
Solved! As stated by Hemant in this Thread, you also have to pass the action that you import as props into the component. Works like a charm now :)

Unable to handle error: `middleware is not a function' in redux-promise-middleware?

I am trying to use redux-promise-middleware in my app, but when I am trying to run my app error comes with an error message: 'middleware is not a function or middleware is null'.
I tried to use middleware without a function as suggested in redux async docs, but still error is coming.
configureStore.js
import { createStore, applyMiddleware } from 'redux'
import app from './reducers/index';
import PromiseMiddleware from 'redux-promise-middleware';
const configureStore = () => {
let middleware = applyMiddleware(PromiseMiddleware());
let store = createStore(app, middleware);
return store
};
export default configureStore;
index.js
import React from 'react'
import { AppRegistry } from 'react-native';
import App from './App';
import { Provider } from 'react-redux'
import configureStore from './configureStore'
const store = configureStore();
const ReduxMiddleware = () => {
<Provider store={store}>
<App />
</Provider>
}
AppRegistry.registerComponent('ReduxMiddleware', () => ReduxMiddleware);
Please anybody, suggest to me that why I am facing this error.
I am new to redux.
import promiseMiddleware from 'redux-promise-middleware';
composeStoreWithMiddleware = applyMiddleware(
promiseMiddleware,
)(createStore);
And not : PromiseMiddleware()
(not uppercase and w/o () )

PersistGatae causes Cannot read property 'subscribe' of undefined error

I am trying to figure put how to use Redux-Persist. I have the following code in my index.js:
import { AppRegistry, View } from "react-native";
import React from "react";
import App from "./App";
import { name as appName } from "./app.json";
import { Provider } from "react-redux";
import { PersistGate } from "redux-persist/integration/react";
import storeConfig from "./app/config/store";
const AppRedux = () => (
<Provider store={storeConfig.store}>
<PersistGate presistor={storeConfig.persistor} loading={null}>
<App />
</PersistGate>
</Provider>
);
AppRegistry.registerComponent(appName, () => AppRedux);
When I run it I get the following message:
Unhandled JS Exception: TypeError: Cannot read property 'subscribe' of undefined
BUT, When i comment out PersistGate I have no problems and my store gets rehydrated.
The reason I am trying to keep PersistGate is to have splash screen while rehydrating. Any suggestions on how to solve this problem?
P.S. This is what I have in store file:
export default () => {
const pReducer = persistReducer(persistConfig, reducers);
const store = createStore(pReducer, {}, applyMiddleware(logger));
const persistor = persistStore(store);
return { store, persistor };
};

Could not find "store" in the context of "Connect(App)" even after uses provider or connect

I'm trying to use redux in my project I make my code like tutorial but it won't work and give error
I see most of the question about this error but I already done what they say the soultion like I should warp my root componet with provider or use connect
Invariant Violation: Could not find "store" in the context of "Connect(App)". Either wrap the root component in a <Provider>, or pass a custom React context provider to <Provider> and the corresponding React context consumer to Connect(App) in connect options.
index.js
import React from 'react';
import {AppRegistry} from 'react-native';
import {Provider} from 'react-redux';
import App from './App';
import { name as appName } from './app.json';
import placesReducer from './src/store/reducers/places';
import{createStore} from 'redux'
import configureStore from './src/store/configureStore';
const store = configureStore();
const RNRedux = () => (
<Provider store={store}>
<App/>
</Provider>
);
AppRegistry.registerComponent(appName, () => RNRedux);
APP.js
import React, { Component } from "react";
import { StyleSheet, View } from "react-native";
import { connect } from "react-redux";
class App extends Component {
render() {
return (
<View style={styles.container}>
some code
</View>
);
}
}
const mapStateToProps = state => {
return {
some code
};
};
const mapDispatchToProps = dispatch => {
return {
some code
};
};
export default connect(mapStateToProps, mapDispatchToProps)(App);
my store
import {combineReducers, createStore} from 'redux';
import placesReducer from './reducers/places';
const rootReducer = combineReducers({
places: placesReducer
});
const configureStore = () => createStore(rootReducer)
export default configureStore;
const configureStore = () => createStore(rootReducer)
configureStore in this case is a variable with the return value of createStore, you most likely want it to be a function.
do you have to call configureStore as callback?
can you call it directly like that:
const configureStore = createStore(rootReducer);

Persist store with Redux Toolkit in React-native

I am using redux-persist with redux toolkit.
here is my store configuration.
I haven't implemented or configured store before.
I intend to persist user state after login.
Currently after login, if I reload app in emulator it always goes back to login screen.
is my store configured properly?
updated store file:
import {configureStore} from '#reduxjs/toolkit';
import authReducer from '../features/login/authSlice';
import AsyncStorage from '#react-native-community/async-storage';
import {persistReducer, persistStore} from 'redux-persist';
import {combineReducers} from 'redux';
import hardSet from 'redux-persist/lib/stateReconciler/hardSet';
import autoMergeLevel2 from 'redux-persist/lib/stateReconciler/autoMergeLevel2';
const reducers = combineReducers({
auth: authReducer,
// other reducers goes here...
});
const persistConfig = {
key: 'root',
storage: AsyncStorage,
// stateReconciler: hardSet,
};
const _persistedReducer = persistReducer(persistConfig, reducers);
export const store = configureStore({
reducer: _persistedReducer,
});
export const persistor = persistStore(store);
My index.js file where i wrap my root component with PersistGate
import React from 'react';
import {AppRegistry} from 'react-native';
import App from './App';
import {name as appName} from './app.json';
import {store, persistor} from './src/stores/store';
import {Provider} from 'react-redux';
import {storeUser, storeRefreshToken} from './src/features/login/authSlice';
import {PersistGate} from 'redux-persist/lib/integration/react';
const RNRedux = () => (
<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
<App />
</PersistGate>
</Provider>
);
AppRegistry.registerComponent(appName, () => RNRedux);
Error I get currently:
I think you need to use persistStore. You should store your app store in persistStore and then use persistGate.
PersistGate delays the rendering of your app's UI until your persisted state has been retrieved and saved to redux.
So, your store file can be :
import { persistStore } from 'redux-persist';
const persistor = persistStore(store);
export { persistor, store };
And your app.js will be :
import { store, persistor } from 'path_to_your_store/store';
<Provider store={store}>
<PersistGate persistor={persistor}>
</App>
</PersistGate>
</Provider>
This appears to be an issue with redux-persist passing a function as an action type which is not recommended by the Redux devs. Redux Toolkit was developed with defaults to help avoid the creation of breakable code. It's RTK's default middleware "serializableCheck" that throws this error. This middleware can be disabled outright or just for specific actions, and both methods are provided by example in answers to this SO question. RTK middleware documentation here for quick reference.
Here's a blanket solution that should work for you:
- import {configureStore} from '#reduxjs/toolkit';
+ import {configureStore, getDefaultMiddleware} from '#reduxjs/toolkit';
...
export const store = configureStore({
reducer: _persistedReducer,
+ middleware: getDefaultMiddleware({
+ serializableCheck: false
+ }),
});
...