React Native: Unable to use `store.dispatch` using redux-saga - react-native

I am using react-native 0.50.3 , I am trying to dispatch a navigation action but I get this error:
undefined is not an object (evaluating '_reducers2.default')
import configureStore from '../../../configureStore'
const store = configureStore(); <-- error points here
class childComp extends Component {
//...
goToProfile = () => {
store.dispatch(NavigationActions.navigate({routeName: 'Profile'}));
}
}
export default childComp;
configureStore.js:
import { createStore, applyMiddleware } from 'redux';
import app from './src/reducers';
import createSagaMiddleware from 'redux-saga';
import rootSaga from './sagas';
const sagaMiddleware = createSagaMiddleware()
export default function configureStore(){
const store = createStore(app, applyMiddleware(sagaMiddleware)) <-- also error points here
sagaMiddleware.run(rootSaga)
return store;
}
I have already used store.dispatch in index.js and it works fine.
Reducers
import { combineReducers } from 'redux';
import { TopLevelNavigator } from '../navigation/TopLevelNavigation/TopLevelConfig';
import { MainTabBar } from '../navigation/MainTabBar/MainTabBarConfig';
import { UserFormsTabBar } from '../navigation/UserFormsTabBar/UserFormsTabBarConfig';
import authReducer from './auth';
import employerReducer from './employer';
import contactReducer from './contact';
import personalReducer from './personal';
import bioReducer from './bio';
import saveFormsData from './saveData';
import saveAllFormsData from './saveFormsData';
import peopleReducer from './getPeople';
import currentUserReducer from './getCurrentUser';
const rootReducer = combineReducers({
TopLevelNavigationReducer: (state, action) => TopLevelNavigator.router.getStateForAction(action, state),
mainTabBarNavigationReducer: (state, action) => MainTabBar.router.getStateForAction(action, state),
userFormsTabBarNavigationReducer: (state, action) => UserFormsTabBar.router.getStateForAction(action, state),
authReducer,
employerReducer,
contactReducer,
personalReducer,
bioReducer,
saveFormsData,
saveAllFormsData,
peopleReducer,
currentUserReducer,
});
export default rootReducer;

Related

Redux Toolkit :Error: "reducer" is a required argument, and must be a function or an object of functions that can be passed to combineReducers

With this code i got no error.
import {combineReducers, configureStore} from '#reduxjs/toolkit';
import {menuReducer as menu} from './menu';
import {cartReducer as cart} from './shoppingCart';
import {optionsReducer as options} from './optionsItem';
import {homeReducer as home} from './home';
import {rewardReducer as reward} from './reward';
import {ordersReducer as orders} from './orders';
import {authReducer as auth} from './auth';
import giftCardReducer from '../store/giftCard';
import paymentMethodReducer from './paymentMethod';
import paymentToken from "./paymentToken";
import qRCode from "./qRCode";
import orderHistory from './orderHistory';
import orderDetail from './orderDetail';
import showCompletedOrder from './showCompletedOrder';
import paymentOptionsSummary from './paymentOptionsSummary';
import usersUpdate from './usersUpdate';
import referAFriend from './referAFriend';
import resetPassword from './resetPassword';
const reducer = combineReducers({
menu,
auth,
giftCardReducer,
paymentMethodReducer,
cart,
options,
orders,
home,
reward,
paymentToken,
qRCode,
orderHistory,
orderDetail,
showCompletedOrder,
paymentOptionsSummary,
usersUpdate,
referAFriend,
resetPassword
});
export {menuActions} from './menu';
export {cartActions} from './shoppingCart';
export {optionsActions} from './optionsItem';
export {ordersActions} from './orders';
export {authActions} from './auth';
export {homeActions} from './home';
export {rewardActions} from './reward';
export type rootState = ReturnType<typeof reducer>;
export default configureStore({
reducer:reducer
});
const rootReducer = (state, action) => {
if (action.type === 'auth/logout') { // check for action type
state = undefined;
}
return reducer(state, action);
};
if i change this code with below one i got error mentioned.
import {combineReducers, configureStore} from '#reduxjs/toolkit';
import {menuReducer as menu} from './menu';
import {cartReducer as cart} from './shoppingCart';
import {optionsReducer as options} from './optionsItem';
import {homeReducer as home} from './home';
import {rewardReducer as reward} from './reward';
import {ordersReducer as orders} from './orders';
import {authReducer as auth} from './auth';
import giftCardReducer from '../store/giftCard';
import paymentMethodReducer from './paymentMethod';
import paymentToken from "./paymentToken";
import qRCode from "./qRCode";
import orderHistory from './orderHistory';
import orderDetail from './orderDetail';
import showCompletedOrder from './showCompletedOrder';
import paymentOptionsSummary from './paymentOptionsSummary';
import usersUpdate from './usersUpdate';
import referAFriend from './referAFriend';
import resetPassword from './resetPassword';
const reducer = combineReducers({
menu,
auth,
giftCardReducer,
paymentMethodReducer,
cart,
options,
orders,
home,
reward,
paymentToken,
qRCode,
orderHistory,
orderDetail,
showCompletedOrder,
paymentOptionsSummary,
usersUpdate,
referAFriend,
resetPassword
});
export {menuActions} from './menu';
export {cartActions} from './shoppingCart';
export {optionsActions} from './optionsItem';
export {ordersActions} from './orders';
export {authActions} from './auth';
export {homeActions} from './home';
export {rewardActions} from './reward';
export type rootState = ReturnType<typeof reducer>;
export default configureStore({
reducer:rootReducer
});
const rootReducer = (state, action) => {
if (action.type === 'auth/logout') { // check for action type
state = undefined;
}
return reducer(state, action);
};
Please help me.Thanks in advance.
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
I also had this problem in React when I configured my redux store inside my client index.js file. This was my code that produces the error:
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import { configureStore } from "#reduxjs/toolkit";
import { Provider } from "react-redux";
import allReducers from "./redux/reducer";
const store = configureStore({ allReducers });
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById("root")
);
QUICK FIX: As the error suggests, "reducer" is a required argument... So, I just modified my store constant like so: configureStore({reducer: allReducers}). I just made "reducer" as a key, and passed allReducers as its value. My problem is then fixed.
Try this way
import { configureStore } from '#reduxjs/toolkit'
import { combineReducers } from 'redux'
const reducer = combineReducers({
// here we will be adding reducers
})
const store = configureStore({
reducer,
})
export default store;
Details Here
Actually I got the solution.
This error is shows because i have put the rootReducer function below the configure store that's why reducer id not getting the rootReducer function.
So, when I move it up then its working fine.
my solution was:
const rootReducer = combineReducers({
users: reducer
})
const store = createStore(rootReducer);
canceled braces and change configureStore to createStore
The documentation for configureStore neatly articulates the various options that can be passed in by keyword within the config object that a few of the others have alluded to.
If you are still struggling with this error, be sure to check the documentation here. It is very helpful.

Navigate in action with redux, debug with reactotron error

I try to navigate inside actions of redux, but the command NavigationActions.navigate don't worked, so I installed reactotron to try debug with reactotron, but this cause the error of image, below are the code and de error. Some help me please.
The action
export function* searchByID(action) {
try {
console.log('action', action);
const response = yield call(apiGetProdutoByID, action.idProduto);
console.log('produto', response);
yield put({
type: TypesProdutos.SEARCH_BY_ID,
produto: response.data.data.obj,
});
const produto = yield select(state => state.produtos);
console.log(produto);
**yield put(
NavigationActions.navigate({
routeName: action.route,
params: {produto: produto},
}),**
);
} catch (error) {
console.log(error);
yield put({type: TypesProdutos.FAIL});
}
}
ReactotronConfig.js
import Reactotron from 'reactotron-react-native';
import AsyncStorage from '#react-native-community/async-storage';
import {reactotronRedux as reduxPlugin} from 'reactotron-redux';
import sagaPlugin from 'reactotron-redux-saga';
const reactotron = Reactotron;
Reactotron.setAsyncStorageHandler(AsyncStorage) // AsyncStorage would either come from `react-native` or `#react-native-community/async-storage` depending on where you get it from
.configure() // controls connection & communication settings
.useReactNative() // add all built-in react native plugins
.use(reduxPlugin())
.use(sagaPlugin())
.connect(); // let's connect!
export default reactotron;
index.js
if (__DEV__) {
import('./ReactotronConfig').then(() => console.log('Reactotron Configured'));
}
import {AppRegistry} from 'react-native';
import App from './src';
import {name as appName} from './app.json';
AppRegistry.registerComponent(appName, () => App);
index.js (store)
import {createStore, applyMiddleware} from 'redux';
import createSagaMiddleware from 'redux-saga';
import rootReducer from './ducks';
import rootSaga from './sagas';
import Reactotron from 'reactotron-react-native';
const sagaMonitor = Reactotron.createSagaMonitor;
const sagaMiddleware = createSagaMiddleware({sagaMonitor});
const middleware = applyMiddleware(sagaMiddleware);
const store = createStore(rootReducer, middleware);
sagaMiddleware.run(rootSaga);
export default store;
error:
error
After command npm install and make this modifications in the file where I export store, the app worked.
import {createStore, applyMiddleware, compose} from 'redux';
import createSagaMiddleware from 'redux-saga';
import rootReducer from './ducks';
import rootSaga from './sagas';
import Reactotron from 'reactotron-react-native';
import ReactotronConfig from '../../ReactotronConfig';
const sagaMonitor = Reactotron.createSagaMonitor;
const sagaMiddleware = createSagaMiddleware({sagaMonitor});
const middleware = applyMiddleware(sagaMiddleware);
const store = createStore(
rootReducer,
compose(
middleware,
ReactotronConfig.createEnhancer(),
),
);
sagaMiddleware.run(rootSaga);
export default store;

Store does not have a valid Reducer - How to pass a combined reducer into store?

I'm trying to get my head around Redux and other answers are making it more of an obstacle at this point.
reducers/index.js
import { combineReducers } from 'redux';
import photoInputPost from './photoInputPost'
import cameraInputPost from './cameraInputPost'
import textInputPost from './textInputPost'
export default rootReducer = combineReducers({
photoInputPost,
textInputPost,
cameraInputPost
})
store/index.js:
import { createStore } from 'redux'
import reducer from './../reducers/index'
export default Store = createStore(reducer)
One of the reducers, textInputPost.js
const textInputReducer = (initialState, action) => {
console.log('textInputReducer', action);
switch(action.type){
case 'ADD_INPUT_TEXT':
return { textInputValue: action.text };
default:
return state;
}
}
Not really sure what's going wrong but I'm probably passing the combined reducer in the wrong way.
You can create a rootReducer file as:
import { combineReducers } from "redux";
import reducer1 from "./reducer1";
import reducer2 from "./reducer2";
const rootReducer = combineReducers({ reducer1, reducer2 });
export default rootReducer;
...and in your index.js, add this rootReducer as:
import { createStore } from "redux";
import { Provider } from "react-redux";
import rootReducer from "./reducers/rootReducer";
import App from "./components/app";
import React from "react";
import ReactDom from "react-dom";
const store = createStore(rootReducer);
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById("root")
);

How to fix this error "combineReducers" are read-only. in react-native/react-redux

I'm creating a new todo app in react-native using redux.
On setting up the rootReducer using combineReducers i'm getting the following error.
"combineReducers" is read-only.
// reducers/todos.js
let nextId = 0;
const todos = (state = [], action) => {
switch (action.type) {
case 'ADD_TODO':
return [
...state, {
id: nextId++,
text: action.text,
completed: false,
}
]
case 'TOGGLE_TODO':
return state.map(todo =>
(todo.id === action.id) ? { ...todos, completed: !todo.completed } : todo)
default:
return state
}
}
export default todos;
created a visibility filter to toggle the todo state.
// reducers/visibilityFilter.js
const visibilityFilter = (state='SHOW_ALL', action) =>{
return state;
}
export default visibilityFilter;
combining the both reducers into index file.
// reducers/index.js
import { combineReducers } from 'redux';
import todos from './todos';
import visibilityFilter from './visibilityFilter';
export default combineReducers = combineReducers({
todos,
visibilityFilter
})
Here is my store file
import { createStore } from 'redux';
import rootReducer from '../reducers';
export default store = createStore(rootReducer);
As the message clearly states, you are not allowed to reassign combineReducers. Just change your code to the following, as described in the docs:
export default rootReducer = combineReducers({
todos,
visibilityFilter
})
Why do you have this like this?
export default combineReducers = combineReducers({
todos,
visibilityFilter
})
combineReducers() are written in this manner:
import { combineReducers } from "redux";
export default combineReducers({
todos: () => {
return {};
}
});
Give that a try and remember a reducer must always return an object, a string or a number, this is the minimum requirement for getting started with reducers in order to ensure your app doesn't break and that you can get some content to the screen.
Also, you don't necessarily need to identify your combineReducers() as rootReducer, you can just put it together like so:
import { createStore, compose, applyMiddleware } from "redux";
import thunk from "redux-thunk";
import reducers from "../reducers";
const store = createStore(reducers, {}, compose(applyMiddleware(thunk)));
export default store;
Lastly, when you have created your store, you need to import it back to your App.js and wire it up with the Provider tag like so for example:
import React from "react";
import { StyleSheet, Text, View } from "react-native";
import {
createBottomTabNavigator,
createStackNavigator,
createAppContainer
} from "react-navigation";
import { Provider } from "react-redux";
import store from "./store";
And:
export default class App extends React.Component {
render() {
return (
<Provider store={store}>
<View style={styles.container}>
<MainNavigator />
</View>
</Provider>
);
}
}

redux-persist: undefined is not an object (evaluating store.getState)

It's my first time using Redux and Redux Persist.
I got this error when I tried to run my application (in index.js line 20):
TypeError: undefined is not an object (evaluating 'store.getState')
index.js:
import React from 'react';
import { AppRegistry } from 'react-native';
import App from './App';
import { name as appName } from './app.json';
import { Provider } from 'react-redux';
import {persistor, store}from './store/configureStore';
import { PersistGate } from 'redux-persist/integration/react';
const RNRedux = () => (
<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
<App/>
</PersistGate>
</Provider>
)
AppRegistry.registerComponent(appName, () => RNRedux);
App.js:
import {createStackNavigator, createAppContainer} from 'react-navigation';
import Register from './components/Register';
import Home from './components/Home';
import Login from './components/Login';
const AppNavigator = createStackNavigator({
HomeScreen: {
screen: Home,
navigationOptions: {
title: 'Home',
header: null
}
},
LoginScreen: {screen: Login},
RegisterScreen: {
screen: Register,
navigationOptions: {
title: 'Register'
}
}
});
const App = createAppContainer(AppNavigator);
export default App;
configureStore.js:
import { createStore, combineReducers } from 'redux';
import userReducer from './reducers/user';
import { persistStore, persistCombineReducers, persistReducer } from 'redux-persist';
import storage from 'redux-persist/es/storage' // default: localStorage if web, AsyncStorage if react-native
import { AsyncStorage } from 'react-native';
const persistConfig = {
key: 'root',
storage
};
const rootReducer = persistCombineReducers(persistConfig, {
user: userReducer
});
const persistedReducer = persistReducer(persistConfig, rootReducer);
export default () => {
let store = createStore(persistedReducer)
let persistor = persistStore(store, {storage: AsyncStorage})
return { store, persistor };
}
You are exporting a function from configureStore.js but trying to import {persistor, store} in index.js.
You should import the function instead and call it.
For example:
import configureStore from './store/configureStore';
const {store, persistor} = configureStore();
import thunk from "redux-thunk";
import { persistStore, persistReducer } from "redux-persist";
import { AsyncStorage } from "react-native";
import logger from "redux-logger";
const persistConfig = {
key: "root",
storage: AsyncStorage,
whitelist: ["authReducer"],
};
const persistedReducer = persistReducer(persistConfig, rootReducer);
const middleWares = [thunk, logger];
const store = createStore(persistedReducer, applyMiddleware(...middleWares));
let persistor = persistStore(store);
export default { store, persistor };
I was getting the same error "undefined is not an object (evaluating 'store.getState')"
My issue was solved after I removed the default keyword after export
export { store, persistor };