I have been using react-native-router-flux in my app and configured the store and it works like a charm.
I am now planning to use react-navigation v2.8 in my app and i am struggling to complete the configureStore.
I supposed that the configureStore would be used as is from the react-native-router-flux example. Below is the sample code from my working react-native-router-flux sample.
/* global __DEV__ */
import { Router } from 'react-native-router-flux'; //this is not to be used
in react-navigation
import { connect } from 'react-redux';
import { createStore, applyMiddleware, compose } from 'redux';
import { persistStore } from 'redux-persist';
import ReduxPromise from 'redux-promise';
import thunk from 'redux-thunk';
import { createLogger } from 'redux-logger';
import reducers from './index';
connect()(Router); //ROuter is not avaible in react-navigation
let middleware;
if (__DEV__) {
const logger = createLogger();
middleware = [thunk, ReduxPromise, logger];
//middleware = [thunk, ReduxPromise];
} else {
middleware = [thunk, ReduxPromise];
}
export function configureStore() {
const store = compose(applyMiddleware(...middleware))(
createStore
)(reducers);
const persistor = persistStore(store);
return { persistor, store };
}
export const { persistor, store } = configureStore();
React Navigation can be used as a general JSX Component that can be enclosed within the Provider and thus the whole UI tree will have the store available inside the context. So you can just initialize the store in your app's root, keep it as a state variable inside
it and pass it to the context using Provider.
Code for configuring your store and making it available down in your UI tree made using React Navigation should look like below:
Your Root component should look like this
import React, {Component} from 'react';
import {Provider} from 'react-redux';
import AppStack from './app/AppNavigation';
import getStore from './app/store';
export default class App extends Component {
constructor (props) {
super(props);
this.state = {
store : getStore()
}
}
render() {
return (
<Provider store={this.state.store} >
<AppStack /> . // This is your React Navigation Stack.
</Provider>
);
}
}
and your getStore should look like this:
import { createStore } from 'redux';
import reducers from './reducers';
export default function getStore () {
const enhancer = compose(
applyMiddleware(
//your middlewares here..
)
);
const store = createStore(reducers);
return store;
}
and the AppStack can look like this:
import {createStackNavigator} from 'react-navigation';
import FirstScreen from './components/FirstScreen';
export default AppStack = createStackNavigator({
Screen1: {
screen: FirstScreen,
//other routes....
},
});
This is just a mere simplest possible example.
Related
In my app.js file, I have a Navigator and I am attempting to wrap it in a redux store in order to control the state throughout my app. I am receiving this error though:
"Invariant Violation: The navigation prop is missing for this navigator. In react-navigation v3 and v4 you must set up your app container directly."
How can I properly wrap my navigator in the Redux store so I can use it?
App.js
import React from 'react';
import { registerRootComponent } from 'expo';
import { View, Text, Button } from 'react-native';
import { createAppContainer, createStackNavigator } from 'react-navigation';
import { createStackNavigator } from 'react-navigation-stack';
import { createStore, applyMiddleware } from 'redux'
import { Provider } from 'react-redux'
import thunkMiddleware from 'redux-thunk'
import reducer from './store/reducers'
// Components
import Home from './Screens/Home';
import Landing from './Screens/Landing';
import Tasks from './Screens/Tasks';
import Login from './Screens/Login';
const middleware = applyMiddleware(thunkMiddleware)
const store = createStore(reducer, middleware)
const Navigator = createStackNavigator({
Tasks: {screen: Tasks},
Landing: {screen: Landing},
Home: { screen: Home },
});
export default class App extends React.Component {
render() {
return (
<Provider store={store}>
<Navigator />
</Provider>
)
}
}
I figure out how to accomplish this. Below is the updated code with my App wrapped in a store container.
import { createStore, applyMiddleware } from 'redux'
import { Provider } from 'react-redux'
import thunkMiddleware from 'redux-thunk'
import reducer from './store/reducers'
// Components
import Home from './Screens/Home';
import Landing from './Screens/Landing';
import Tasks from './Screens/Tasks';
import Login from './Screens/Login';
const middleware = applyMiddleware(thunkMiddleware)
const store = createStore(reducer, middleware)
const Navigator = createStackNavigator({
Tasks: {screen: Tasks},
Landing: {screen: Landing},
Home: { screen: Home },
});
//ADDED THIS
const App_1 = createAppContainer(Navigator);
export default class App extends React.Component {
render() {
return (
<Provider store={store}>
<App_1 /> //UPDATED
</Provider>
)
}
}
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);
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>
);
}
}
I'm using react-navigation and redux for navigation between screens I'm getting an error instead.
Invariant Violation: createReduxBoundAddListener is deprecated in
react-navigation-redux-helpers#2.0.0! Please use reduxifyNavigator
I don't know how to fix it please help me out.
App.js
import React from 'react';
import { Provider } from "react-redux";
import store from "./src/redux/store"
import { createReduxBoundAddListener } from "react- navigation-redux-helpers";
import AppWithNavigationState from "./src/navigators/AppNavigator";
export default class App extends React.Component {
render() {
return (
<Provider store={store}>
//Here Im getting an error regarding creacteReduxBoundAddListener
<AppWithNavigationState listener{createReduxBoundAddListener("root")}/>
</Provider>
);
}
}
AppNavigator.js file
import React, { Component } from 'react';
import { View, Text } from 'react-native';
import {connect} from "react-redux";
import {PropTypes} from 'prop-types';
import {addNavigationHelpers,createStackNavigator } from "react-navigation";
import LoggedOut from "../screens/LoggedOut";
import LogIn from "../screens/Login";
import ForgotPassword from "../screens/ForgotPassword";
// created screens using createStackNavigator
export const AppNavigator = createStackNavigator({
LoggedOut:{screen:LoggedOut},
LogIn:{screen:LogIn},
ForgotPassword:{screen:ForgotPassword},
});
const AppWithNavigationState = ({ dispatch,nav,listener}) =>{
<AppNavigator navigation=
{addNavigationHelpers({dispatch,state:nav,addListener:listener})}/>
};
AppWithNavigationState.propTypes = {
dispatch:PropTypes.func.isRequired,
nav:PropTypes.object.isRequired
};
const mapStateToProps = state =>({
nav:state.nav,
});
export default connect(mapStateToProps)(AppWithNavigationState);
navigation.js
import {AppNavigator} from "../../navigators/AppNavigator";
const firstAction =
AppNavigator.router.getActionForPathAndParams("LoggedOut"); //decide which
//screen will
//load first
const initialNavState = AppNavigator.router.getStateForAction(firstAction);
export const nav = (state=initialNavState, action)=>{
let nextState = AppNavigator.router.getStateForAction(action,state);
return nextState || state;
}
You can check this repo https://github.com/JaiDeves/AirBnB-React, I've updated the code with the newer version of react-navigation.
I am trying to use switch navigator with redux. following is my code.
import { createSwitchNavigator, createStackNavigator } from 'react-navigation';
import LoginScreen from '../screens/LoginScreen';
import EmployeeListScreen from '../screens/EmployeeListScreen';
import DetailsView from '../screens/EmployeeDetailViewScreen';
import EmployeeForm from '../screens/EmployeeForm';
import AuthLoadingScreen from "../screens/AuthLoadingScreen.js";
import {connect } from "react-redux";
import { AppNavigator } from "../navigations/AppNavigator.js";
const AppStack = createStackNavigator({
List:{screen:EmployeeListScreen},
Detail:{screen:DetailsView},
Form:{screen:EmployeeForm}
});
const AuthStack = createStackNavigator({ Login: LoginScreen });
export const AuthNavigator = createSwitchNavigator(
{
AuthLoading: AuthLoadingScreen,
App: AppNavigator,
Auth: AuthStack,
},
{
initialRouteName: 'AuthLoading',
}
);
const AuthWithNavigationState = ({ dispatch, nav }) => (
<AuthNavigator />
);
const mapStateToProps = state => ({
nav: state.nav,
});
export default connect(mapStateToProps)(AuthWithNavigationState);
I'm importing this component is my App.js file and using it as follows to connect with redux store but it is giving me error like, React is not defined and error is located at connect(AuthWithNavigationState)
import React from 'react';
import { Provider } from 'react-redux';
import { createStore,applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import AppReducer from './src/reducers/AppReducer';
import AuthWithNavigationState from './src/navigations/AuthNavigator.js';
const store = createStore(AppReducer,applyMiddleware(thunk));
export default class App extends React.Component {
render() {
return (
<Provider store={store}>
<AuthWithNavigationState/>
</Provider>
);
}
}
I've tried to follow instruction from below link but still I am getting the same error.
how can i integrate redux store to react native?
Can anyone tell me what is wrong with my code?
after too much trying, I figure out that, The switch navigator don't need to be connect to the store, so below step was incorrect.
const AuthWithNavigationState = ({ dispatch, nav }) => (
<AuthNavigator />
);
const mapStateToProps = state => ({
nav: state.nav,
});
export default connect(mapStateToProps)(AuthWithNavigationState);
I simply exported AuthNavigator and imported in App.js and this worked for me.
import React from 'react';
import { Provider } from 'react-redux';
import { createStore,applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import AppReducer from './src/reducers/AppReducer';
import AuthNavigatorfrom './src/navigations/AuthNavigator.js';
const store = createStore(AppReducer,applyMiddleware(thunk));
export default class App extends React.Component {
render() {
return (
<Provider store={store}>
<AuthNavigator/>
</Provider>
);
}
}