Giter VIP home page Giter VIP logo

redux-helpers's Introduction

react-navigation-redux-helpers

This package allows the user to manage their React Navigation state from within Redux.

DEPRECATED as of React Navigation 5

React Navigation no longer supports storing its state within Redux. You should be able to refactor your custom navigation logic into custom navigators, custom routers, and onStateChange callbacks.

How it works

  1. In React Navigation, "containers" wrap navigators, and own the state for that navigator and any nested navigators. This package implements a container that uses Redux as a backing store.
  2. A Redux middleware is used so that any events that mutate the navigation state properly trigger React Navigation's event listeners.
  3. Finally, a reducer enables React Navigation actions to mutate the Redux state.

Motivation

Most projects that are using both Redux and React Navigation don't need this library. Things like state persistence and BackHandler behavior aren't handled directly by createReduxContainer, but are handled by the default createAppContainer. However, there are some things this library makes easier:

  1. It's possible to implement custom actions, allowing you to manipulate the navigation state in ways that aren't possible with the stock React Navigation actions. Though it's possible to implement custom routers in React Navigation to do this, it's arguably cleaner via Redux. (If you want animations to run on your action, make sure to set isTransitioning to true!)
  2. This library allows the user to customize the persistence of their navigation state. For instance, you could choose to persist your navigation state in encrypted storage. Most users don't need this, as there are no practical downsides to handling persistence of navigation state and Redux state separately. Note that stock React Navigation supports some basic degree of persistence customization.
  3. You can implement custom reducer behavior to validate state and maintain consistency between navigation state and other application state. This is again possible with custom routers, but likely cleaner to implement without, especially in the context of an existing Redux setup.

Installation

yarn add react-navigation-redux-helpers

or

npm install --save react-navigation-redux-helpers

Example

import {
  createStackNavigator,
} from 'react-navigation';
import {
  createStore,
  applyMiddleware,
  combineReducers,
} from 'redux';
import {
  createReduxContainer,
  createReactNavigationReduxMiddleware,
  createNavigationReducer,
} from 'react-navigation-redux-helpers';
import { Provider, connect } from 'react-redux';
import React from 'react';

const AppNavigator = createStackNavigator(AppRouteConfigs);

const navReducer = createNavigationReducer(AppNavigator);
const appReducer = combineReducers({
  nav: navReducer,
  ...
});

const middleware = createReactNavigationReduxMiddleware(
  state => state.nav,
);

const App = createReduxContainer(AppNavigator);
const mapStateToProps = (state) => ({
  state: state.nav,
});
const AppWithNavigationState = connect(mapStateToProps)(App);

const store = createStore(
  appReducer,
  applyMiddleware(middleware),
);

class Root extends React.Component {
  render() {
    return (
      <Provider store={store}>
        <AppWithNavigationState />
      </Provider>
    );
  }
}

API

createReactNavigationReduxMiddleware (required)

function createReactNavigationReduxMiddleware<State: {}>(
  navStateSelector: (state: State) => NavigationState,
  key?: string,
): Middleware<State, *, *>;
  • Returns a middleware that can be applied to a Redux store.
  • Param navStateSelector selects the navigation state from your store.
  • Param key needs to be unique for the Redux store and consistent with the call to createReduxContainer below. You can leave it out if you only have one store.

createReduxContainer (required)

function createReduxContainer(
  navigator: Navigator,
  key?: string,
): React.ComponentType<{ state: NavigationState, dispatch: Dispatch }>;
  • Returns a HOC (higher-order component) that wraps your root navigator.
  • Param navigator is your root navigator (React component).
  • Param key needs to be consistent with the call to createReactNavigationReduxMiddleware above. You can leave it out if you only have one store.
  • Returns a component to use in place of your root navigator. Pass it state and dispatch props that you get via react-redux's connect.

createNavigationReducer (optional)

function createNavigationReducer(navigator: Navigator): Reducer<*, *>;
  • Call createNavigationReducer in the global scope to construct a navigation reducer.
  • This basically just wraps navigator.router.getStateForAction, which you can call directly if you'd prefer.
  • Param navigator is your root navigator (React component).
  • Call this reducer from your master reducer, or combine using combineReducers.

Miscellaneous

Mocking tests

To make Jest tests work with your React Navigation app, you need to change the Jest preset in your package.json:

"jest": {
  "preset": "react-native",
  "transformIgnorePatterns": [
    "node_modules/(?!(jest-)?react-native|@?react-navigation|react-navigation-redux-helpers)"
  ]
}

Back button

Here is a code snippet that demonstrates how the user might handle the hardware back button on platforms like Android:

import React from "react";
import { BackHandler } from "react-native";
import { NavigationActions } from "react-navigation";

/* your other setup code here! this is not a runnable snippet */

class ReduxNavigation extends React.Component {
  componentDidMount() {
    BackHandler.addEventListener("hardwareBackPress", this.onBackPress);
  }

  componentWillUnmount() {
    BackHandler.removeEventListener("hardwareBackPress", this.onBackPress);
  }

  onBackPress = () => {
    const { dispatch, nav } = this.props;
    if (nav.index === 0) {
      return false;
    }

    dispatch(NavigationActions.back());
    return true;
  };

  render() {
    /* more setup code here! this is not a runnable snippet */
    return <AppNavigator navigation={navigation} />;
  }
}

redux-helpers's People

Contributors

ashoat avatar ericvicenti avatar jpaas avatar jshosomichi avatar lebedev avatar mbernardy avatar ozzieorca avatar rodrigoelp avatar serhiipalash avatar vtserman avatar vyshkant avatar wd avatar yordis avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

redux-helpers's Issues

default namespaces

I've noticed much of the initial setup has to do with simply assigning the "nav" and "root" namespace, I wonder if it would be beneficial to simply assign these by default, and use optional parameters to change these namespaces. The purpose being much of the initial code, and sample, would be minimized for introductory users.

Errors setting up app with redux

I set up a project with redux, and separated things into different files for organizational purposes, and was getting all kinds of errors, mainly Navigator.router.getStateForAction returning null/undefined. So I set up a snack to reproduce the issue, but to start with, followed the documentation example exactly, but I can't get it to run (it says failed to import module 'ren', etc...).

Here's the snack repo: https://snack.expo.io/@buishi/react-navigation-redux-bug

And the original issue on react navigation: react-navigation/react-navigation#3421

Typescript definitions not updated

I'd like to say that I feel the jump to 1.0.0 stable was rushed.

As for the bug

Argument of type '{ dispatch: NavigationDispatch<any>; state: NavigationState; addListener: any; }' is not assignable to parameter of type 'NavigationProp<NavigationState, NavigationStackAction>'.
  Object literal may only specify known properties, and 'addListener' does not exist in type 'NavigationProp<NavigationState, NavigationStackAction>'.

comes from

<Navigator
  navigation={addNavigationHelpers({
	dispatch: this.props.dispatch as NavigationDispatch<any>,
	state: this.props.nav,
	addListener,
  })}
/>

since https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/react-navigation/index.d.ts isn't up to date.

Since I create the store in a separate file from the creation of the Navigator, I had to define an instance property (this.addListener), so that it's created after the redux middleware.

(0 , _reactNavigationReduxHelpers.reduxifyNavigator) is not a function

hello,

i have an issue with the above error:

i use :

"react-navigation": "2.4.0",
"react-navigation-redux-helpers": "^2.0.0-beta.1",

but the issues persists also with the 2.9.3 and 2.0.5 of the redux helpers. The example does not have the issue.

here is the code :

import React, { Component } from "react";
import { connect } from "react-redux";
//import Root from "baseline/navigations/root";
//import { addListener } from "baseline/reducers/nav";
import { createReactNavigationReduxMiddleware } from "react-navigation-redux-helpers";
import { reduxifyNavigator } from "react-navigation-redux-helpers";
import LoginForm from "baseline/components/loginForm";
import { createStackNavigator } from "react-navigation";

/*
class AppNavigator extends Component {
render() {
const { dispatch, nav } = this.props;
const navigation = navigationPropConstructor(dispatch, nav);
return ;
}
}

export default connect(state => ({ nav: state.nav }))(AppNavigator);

*/

const navMiddleware = createReactNavigationReduxMiddleware(
"root",
state => state.nav
);

const RootNavigator = createStackNavigator({
Unauthorized: {
screen: LoginForm
}
});

const AppWithNavigationState = reduxifyNavigator(RootNavigator, "root");

const mapStateToProps = state => ({
state: state.nav
});

const AppNavigator = connect(mapStateToProps)(AppWithNavigationState);

export { AppNavigator, navMiddleware };

the code stops working with the following error:

Console was cleared
ExceptionsManager.js:76 (0 , _reactNavigationReduxHelpers.reduxifyNavigator) is not a function
handleException @ ExceptionsManager.js:76
handleError @ InitializeCore.js:69
reportFatalError @ error-guard.js:42
guardedLoadModule @ require.js:163
metroRequire @ require.js:152
(anonymous) @ notification.ios.js:69
executeApplicationScript @ debuggerWorker.js:40
(anonymous) @ debuggerWorker.js:65
RCTLog.js:47 Required dispatch_sync to load constants for RNDeviceInfo. This may lead to deadlocks
logToConsole @ RCTLog.js:47
logIfNoNativeHook @ RCTLog.js:30
__callFunction @ MessageQueue.js:344
(anonymous) @ MessageQueue.js:107
__guard @ MessageQueue.js:291
callFunctionReturnFlushedQueue @ MessageQueue.js:106
(anonymous) @ debuggerWorker.js:72
RCTLog.js:47 Running application GMO ({
initialProps = {
};
rootTag = 21;
})
ExceptionsManager.js:76 Module AppRegistry is not a registered callable module (calling runApplication)
handleException @ ExceptionsManager.js:76
handleError @ InitializeCore.js:69
reportFatalError @ error-guard.js:42
__guard @ MessageQueue.js:293
callFunctionReturnFlushedQueue @ MessageQueue.js:106
(anonymous) @ debuggerWorker.js:72
ExceptionsManager.js:84 Unhandled JS Exception: (0 , _reactNavigationReduxHelpers.reduxifyNavigator) is not a function
reactConsoleErrorHandler @ ExceptionsManager.js:84
logToConsole @ RCTLog.js:47
logIfNoNativeHook @ RCTLog.js:30
__callFunction @ MessageQueue.js:344
(anonymous) @ MessageQueue.js:107
__guard @ MessageQueue.js:291
callFunctionReturnFlushedQueue @ MessageQueue.js:106
(anonymous) @ debuggerWorker.js:72
ExceptionsManager.js:84 Unhandled JS Exception: Module AppRegistry is not a registered callable module (calling runApplication)
reactConsoleErrorHandler @ ExceptionsManager.js:84
logToConsole @ RCTLog.js:47
logIfNoNativeHook @ RCTLog.js:30
__callFunction @ MessageQueue.js:344
(anonymous) @ MessageQueue.js:107
__guard @ MessageQueue.js:291
callFunctionReturnFlushedQueue @ MessageQueue.js:106
(anonymous) @ debuggerWorker.js:72

any ideas?

thanks
Dirk

addListener dont work

Perfect works in react-navigation 2.2.5 and react-navigation-redux-helpers 1.1.2
Dont works in react-navigation 2.7.0 and react-navigation-redux-helpers 2.0.2
The events focus and blur, only work in first screen,

TypeError: Cannot read property 'router' of undefined

Hello! I get following issue.

My code
// middleware part
middlewares.push(createReactNavigationReduxMiddleware(
  'root',
  state => state.getIn(['navigation']),
))

const RootNavigator = createStackNavigator(AppRouteConfigs)
const AppWithNavigationState = reduxifyNavigator(RootNavigator, 'root')

class ReduxNavigation extends React.Component {
  render() {
    const {
      dispatch,
      navigation,
      language,
      theme,
    } = this.props
    return (
      <AppWithNavigationState
        screenProps={{ language, theme }}
        dispatch={dispatch}
        state={navigation}
      />
    )
  }

const _getSceneKey = state => {
  const nav = state.get('navigation')
  const lastItem = nav && nav.routes && nav.routes.slice(-1)[0]
  return lastItem && lastItem.routeName
}

const mapStateToProps = state => {
  const sceneKey = _getSceneKey(state)
  return {
    navigation: state.getIn(['navigation']),
    language: getLocalization(state),
    sceneKey,
    theme: getTheme(state, 'Theme', ''),
  }
}

const mapDispatchToProps = dispatch =>  ({
  dispatch,
})

export const AppNavigator = connect(mapStateToProps, mapDispatchToProps)(ReduxNavigation)

// Entry point

export default class App extends React.PureComponent {
  constructor(props) {
    super(props)
  }
  render() {
    return (
      <Provider store={store} >
        <AppNavigator />
      </Provider>
    )
  }
}
Error appears in render method of NavigatorReduxWrapper.
"Navigator" is undefined.
Did I do something wrong?
"react-navigation": "^2.3.1", same with "2.7.0"
"react-navigation-redux-helpers": "^2.0.2"

Error: Navigator has both navigation and container props

I've started a new app that's pretty barebones. I've started it with Expo and Redux. Since the new updates to the API I've encountered this error:
image

I've looked at the updated documentation and cannot figure out what's going on here. Anyone else encounter this error?

Here's my code for reference:

import React from 'react';
import { addNavigationHelpers, createStackNavigator } from 'react-navigation';
import { withNetworkConnectivity } from 'react-native-offline';
import { createStore, combineReducers } from 'redux';
import { createReactNavigationReduxMiddleware, reduxifyNavigator } from 'react-navigation-redux-helpers';
import { connect } from 'react-redux';
import { colors } from './../utils/BaseStyles';
import MainPage from './../screens/MainPage';

export const AppNavigator = createStackNavigator({
    Main: { screen: MainPage },
  }, 
  {
    initialRouteName: 'Main',
    navigationOptions: ({ navigation }) => {
      return {
        headerStyle: {
          backgroundColor: colors.primary,
        },
        headerTintColor: colors.primary_white,
        headerTitleStyle: {          
          color: colors.primary_white,
          fontSize: 21
        },
        headerBackTitleStyle: {
          fontSize: 16
        },
      }
    }
  });
  
const middleware = createReactNavigationReduxMiddleware(
  "App",
  state => state.nav,
);

let App = reduxifyNavigator(AppNavigator, "App")

// same error occurs if I use the withNetworkConnectivity or not. If I'm not using it, I rename App on the line above to AppWIthNavigationState

const AppWithNavigationState = withNetworkConnectivity({
  withRedux: true,
  pingServerUrl: 'https://www.google.com'
})(App)

const mapStateToProps = state => ({
  nav: state.nav,
  network: state.network.isConnected,
});

export default connect(mapStateToProps)(AppWithNavigationState);

reduxifyNavigator is causing this.props.navigation.addListener('didFocus') to not work

First thanks for the lib.

Description
I encounter a strange behavior while upgrading to react-navigation@2. Following the example in the docs I noticed that the navigation.AddListener('didFcous' was not working on every screen.

After many hours of debugging, I found out that by removing the reduxifyNavigator all screen that was listening for the event didFocus was working normally.

The issue
This accour when you have a screen that is listening for didFcous/some other events and is connected to redux and by dispatching an action inside of the first didFocus the next didFcous on the stack will not work.

I've used some time to create a repo that can reproduce this issue.
https://github.com/diegoddox/navigation-redux-helper

This is the file that you wanna take a look.
https://github.com/diegoddox/navigation-redux-helper/blob/master/Route.js

dependencies.
react: 16.4.1
react-native: 0.54.0 | 0.56.0
react-navigation: 2.6.2 | 2.8.0
react-navigation-redux-helpers: 2.0.2
react-redux: 5.0.7
redux: 4.0.0

TabNavigator inside StackNavigator has wrong state when going back to default tab

I have a TabNavigator inside a StackNavigator

const Nav = StackNavigator( {
    Tabs: {
      screen: TabNavigator({
          home: {
            screen: HomeScreen, ...
          },
          points: {
            screen: PointsScreen,  ...
          },
          account: {
            screen: AccountScreen,  ...
          }

Now i have a middleware for my redux store which basically logs me the navigation state


Current Behavior

On my android phone i swipe left (to 'points'), then i swipe right (back to 'home' (default)) which is all displayed correctly but in the navigation state, it says that the tabnavigator is still on index 1.

image

Expected Behavior

Normally the navigation state should change correctly. It only doesn't change if i swipe to the "home" (default) tab.

How to reproduce

I use ignite but i did the Redux Integration 'tutorial' (also altered the ignite base code to the correct one in the tutorial) and logged me the navigation state. If there's a need for a replication app i can do one, but it will take some time.

Your Environment

software version
react-navigation 1.5.4
react-navigation-redux-helpers 1.0.3
react-redux 5.0.6

Am i missing something here?

Update 1:

Further investigation with reactotron shows that the navigation state really doesn't change when i swipe to the 'home' tab (but every other navigation works, it's just the 'home' tab (index 0))

Flow errors in middleware.js

Commit 4731556 has introduced flow errors in middleware.js.

On line 9 we have:
Cannot import getNavigationActionCreators because there is no getNavigationActionCreators export in react-navigation.

Online 99 we have:
Cannot assign object literal to navigation because property state is not writable in property state.

Can this be fixed?

Active tab in TabNavigator

I am using redux integration in a very simple fashion.

Current Behavior

Using TabNavigator a user touches a tab to navigate to it - the redux reducer returns no state change so the the screen does not change:

// navigation redux reducer snippet...

[NavigationActions.NAVIGATE]: (state, action) => {
    const newState = AppNavigation.router.getStateForAction(
      action,
      state
    );

    newState.currentRoute = getCurrentRoute(newState).routeName;
    
    // return newState;
   // temporary: stop the screen from changing so return the same state
   return state;
  }

...

The screen DOES NOT change, however, the "active" tab DOES change to the tab that the user touched which is indicated by changing to the activeIcon specified in TabNavigatorConfig.tabBarOptions.tabs.

Expected Behavior

The "active" tab should remain the same as the current screen.

Your Environment

software version
react-navigation 1.5.11
react-native 0.55.3
node 8
npm or yarn yarn

undefined is not an object

After upgrading react-navigation to his latest version (2.18.0 => 3.0.2), I get the following error when navigating back from a tab router.

screenshot 2018-11-28 at 15 40 10

focus / blur events not fired when using getStateForAction

Hi,

I'm using React Navigation integrated with Redux. I've noticed that the focus / blur events are not fired when I change route using getStateForAction.

For example let's imagine a reducer that returns this:

const newState = AppNavigator.router.getStateForAction(NavigationActions.back(args), state);

Is such usage expected to not fire a focus event for the route it lands in, or is it due to a bug?

Thanks!

react native android hardware back button

hello everyone i am new in react-native and stuck at android hardware back button integration in https://reactnavigation.org/docs/en/redux-integration.html#handling-the-hardware-back-button-in-android i am getting error of undefined is not an object (evaluating 'state.routes')
below is my code

`
const AppStack = createStackNavigator({
mainScreen: {
screen: MainScreen,
navigationOptions: ({ navigation }) => ({
header:
})
},
userProfile: {
screen: UserProfile,
navigationOptions: ({ navigation }) => ({
headerTitle: 'Profile',
headerTitleStyle: {
flex: 1,
textAlign: 'center',
alignSelf: 'center'
},
headerRight: (<View style={{ paddingRight: 15 }} >
<Icon onPress={() => navigation.navigate('EditUserProfile')} name="edit" />
)
})
},
editUserProfile: {
screen: EditUserProfile,

navigationOptions: ({ navigation }) => ({
  headerTitle: 'Edit Profile',
  headerTitleStyle: {
  flex: 1,
  textAlign: 'center',
  alignSelf: 'center'
 },
  headerRight: (<View style={{ paddingRight: 15 }} >
                  <Icon onPress={() => navigation.navigate('logout')} name="exit-to-app" />
                </View>)
})

},
PrivateChat: {
screen: PrivateChat,
}
},
logout: {
screen: Logout
}
},
{
initialRouteName: 'mainScreen',
});

const AuthStack = createStackNavigator({
auth: {
screen: Form,
navigationOptions: {
header: null
}
} });

const SwitchNavigator = createSwitchNavigator(
{
AuthLoading: AuthLoadingScreen,
App: AppStack,
Auth: AuthStack
},
{
initialRouteName: 'AuthLoading',
}
);

export const MainNavigation = createDrawerNavigator({
Home: {
screen: SwitchNavigator
}
},
{
contentComponent: (props) => (
<DrawerNavigation {...props} />
)
});

// Create middleware and connect
export const appNavigatorMiddleware = createReactNavigationReduxMiddleware(
'root',
state => state.nav
);

const ReduxAppNavigator = reduxifyNavigator(MainNavigation, 'root');

// create nav component
class ReduxNavigation extends PureComponent {
componentDidMount() {
BackHandler.addEventListener('hardwareBackPress', this.onBackPress);
}

componentWillUnmount() {
BackHandler.removeEventListener('hardwareBackPress', this.onBackPress);
}

onBackPress = () => {
const { dispatch, state } = this.props;
if (state.index === 0) {
return false;
}

dispatch(NavigationActions.back());
return true;

};

render() {
const { dispatch, state } = this.props;
console.log(this.props);
return ;
}
}

const mapStateToProps = state => {
console.log(state.nav);
return { state: state.nav };
};
`

export default connect(mapStateToProps)(ReduxNavigation);

after some changes navigation is working but back button still closing the app and maybe the reason is that state.index is not changing it value it is 0 on every screen i am opening maybe because of switchnavigation

"react-navigation": "^2.5.1",
"react-navigation-redux-helpers": "^2.0.0-beta.1"

Render component is strange when click back arrow with react-redux

I have two class component A and B, i navigate to B by using this.props.navigation.navigate('B') then B component will have a back arrow on headerLeft, when i click the back arrow my data is still using B component data although my screen is A component.

I want to know what is going on when i click the back arrow, i try to console.log in A and B under their render function, i find it will render B > A > B

If i don't click the back arrow button only navigate it by using this.props.navigation.navigate('B or A'), the problem is gone.

My data is come from fetch API with react-redux. I try a simple test to fetch API without react-redux, the problem is gone too.

I have no idea the issue come from react-navigation or react-redux.

Thanks in advance.

Here is my A component file (B component file is similar with A):

import React, { Component } from 'react';
import { 
  View, FlatList, Dimensions, 
  TouchableOpacity, Image,
  ActivityIndicator, Alert, Platform
} from 'react-native';
import { Icon } from 'react-native-elements';
import { connect } from 'react-redux';
import { fetchMainMovieList } from '../actions';

const { width, height } = Dimensions.get('window');
const equalWidth = (width / 2);

class MainActivity extends Component {
  static navigationOptions = ({ navigation }) => ({
    title: 'MainActivity',
    headerLeft: 
      <TouchableOpacity style={{ marginLeft: 10 }} onPress={() => navigation.navigate('DrawerOpen')} >
        <Icon name='menu' />
      </TouchableOpacity>
  });

  componentWillMount() {
    this.props.fetchMainMovieList();
  }

  renderItem({ item }) {
    return (
      <View>
        <Image 
          source={{ uri: item.photoHref }} 
          style={{ height: 220, width: equalWidth }} 
          resizeMode="cover" 
        />
      </View>
    );
  }

  render() {
    const movieData = this.props.movieList;
    console.log('A component this.props=>');
    console.log(this.props);
    if (movieData === []) {
      return (
        <View style={styles.loadingStyle}>
          <ActivityIndicator />
        </View>
      );
    }
    return (
      <View style={{ flex: 1 }}>
        <FlatList
          data={movieData}
          renderItem={this.renderItem} 
          numColumns={2}
          horizontal={false}
          keyExtractor={(item, index) => index} 
        />
      </View>
    );
  }
}

const styles = {
  loadingStyle: {
    flex: 1, 
    flexDirection: 'column', 
    justifyContent: 'center', 
    alignItems: 'center'
  }
};

const mapStateToProps = (state) => {
  const movieList = state.movieList;
  return movieList;
};

export default connect(mapStateToProps, { fetchMainMovieList })(MainActivity);

Current Behavior

What code are you running and what is happening?
Click back arrow on headerLeft in B component to A component , the data is still using B component data.

Expected Behavior

What do you expect should be happening?
Click back arrow on headerLeft in B component to A component , it should render A component only once not B > A > B

Include a screenshot if it makes sense.
2018-05-02 8 52 55

software version
react-navigation "^1.5.11"
react-native "~0.55.2"
react-redux "^5.0.7"

reactNavigationReduxHelpers.reduxifyNavigator

Hello everyone, I'm getting an error after updating react-navigation and react-navigation-redux-helpers.

captura de pantalla 2018-07-09 a la s 11 11 56

This is my code:

import React  from 'react';
import { StatusBar } from 'react-native';
import { applyMiddleware, createStore } from 'redux';
import { Provider, connect } from 'react-redux';
import thunk from 'redux-thunk';
import rootReducer from './src/reducers';
import Navigator from './src/config/routes';
import { persistStore, persistReducer } from 'redux-persist'
import storage from 'redux-persist/lib/storage';
import autoMergeLevel2 from 'redux-persist/lib/stateReconciler/autoMergeLevel2';
import logger from 'redux-logger';

// import {
//     createReduxBoundAddListener,
//     createReactNavigationReduxMiddleware,
// } from 'react-navigation-redux-helpers';

import {
    reduxifyNavigator,
    createReactNavigationReduxMiddleware,
} from 'react-navigation-redux-helpers';

StatusBar.setBarStyle('light-content', true);

// class App extends React.Component {
//     render() {
//         return (
//             <Navigator navigation={{
//                 dispatch: this.props.dispatch,
//                 state: this.props.nav,
//                 addListener,
//             }} />
//         );
//     }
// }

const middleware = createReactNavigationReduxMiddleware(
    "root",
    state => state.nav,
);

const App = reduxifyNavigator(Navigator, "root");

const mapStateToProps = (state) => ({
    state: state.nav,
});

const AppWithNavigationState = connect(mapStateToProps)(App);

const mid = [thunk, logger, middleware];
const persistConfig = {
    key: 'root',
    storage: storage,
    blacklist: ['nav'],
    stateReconciler: autoMergeLevel2
};

const persistedReducer = persistReducer(persistConfig, rootReducer);

const store = createStore(
    persistedReducer,
    applyMiddleware(...mid),
);
const persistor = persistStore(store);


export default () => (
    <Provider store={store} persistor={persistor}>
        <AppWithNavigationState />
    </Provider>
);

"react-navigation": "^2.3.0",
"react-navigation-redux-helpers": "^2.0.0-beta.1",

I already tried with different versions.

Thanks.

bindActionCreators to navigation prop

When doing this: <AppNavigator navigation={addNavigationHelpers({ dispatch, state: nav, addListener, ...bindActionCreators(ActionCreators, dispatch), })} />

I would expect my action creators from ActionCreators to be bound to the navigation property, however they are not. The idea would be to use navigation.someCustomNavigationActionCreator() as opposed to binding navigation-related action creators to the AppNavigator Component itself (in which case I would be following the typical action creator flow of just calling someNavigationActionCreator().

I'm attempting this because I would prefer to follow the pattern of not explicitly using dispatch in my containers, which is how the documented example here is doing it: https://reactnavigation.org/docs/redux-integration.html

Is there not support for binding navigation-related action creators directly to the navigation prop? If so, am I doing something wrong here?

Thanks!

Bundler error in `middleware.js`

Hi

Currently we are updating various packages in our app but it seems we struck a problem with you package:

error: bundling failed: SyntaxError: /<snip>/node_modules/react-navigation-redux-helpers/src/middleware.js: Unexpected token (149:0)

We are running:

    "react": "16.3.1",
    "react-native": "0.55.4",
    "react-redux": "^5.0.7",
    "redux": "^4.0.0",
<snip>
    "react-navigation": "2.3.1",
    "react-navigation-redux-helpers": "2.0.2",

Are we missing something or is this a bug? I have tried numerous version combinations, the error moves around in the file but stays the same.

Thanks & Best
tostr

Use releases and help the community with breaking changes

Hey mates,

I noticed that all my code is broken because of the react-navigation@2 which is fine but I went to Release tab over here on Github for read about the release but I didn't find any release on this package.

I know the documentation was updated but it would be nice if you could use the Release documentation for help the community to understand what changed and how to fix.

What do you think?

Unhandled JS Exception: TypeError: TypeError: Cannot read property 'bind' of undefined

I have some error with reduxify-navigator

Unhandled JS Exception: TypeError: TypeError: Cannot read property 'bind' of undefined

This error is located at:
    in AnimatedComponent (at StackViewCard.js:12)
    in Card (at createPointerEventsContainer.js:28)
    in Container (at StackViewLayout.js:612)
    in RCTView (at View.js:43)
    in RCTView (at View.js:43)
    in StackViewLayout (at withOrientation.js:30)
    in withOrientation (at StackView.js:63)
    in RCTView (at View.js:43)
    in Transitioner (at StackView.js:21)
    in StackView (at createNavigator.js:59)
    in Navigator (at createKeyboardAwareNavigator.js:11)
    in KeyboardAwareNavigator (at createNavigationContainer.js:376)
    in NavigationContainer (at reduxify-navigator.js:63)
    in NavigatorReduxWrapper (at dva-rn.js:56)
    in Router (created by Connect(Router))
    in Connect(Router) (at dva-rn.js:90)
    in Provider (at dva-rn.js:89)
    in Unknown (at renderApplication.js:32)
    in RCTView (at View.js:43)
    in RCTView (at View.js:43)
    in AppContainer (at renderApplication.js:31)

This error is located at:
    in NavigationContainer (at reduxify-navigator.js:63)
    in NavigatorReduxWrapper (at dva-rn.js:56)
    in Router (created by Connect(Router))
    in Connect(Router) (at dva-rn.js:90)
    in Provider (at dva-rn.js:89)
    in Unknown (at renderApplication.js:32)
    in RCTView (at View.js:43)
    in RCTView (at View.js:43)
    in AppContainer (at renderApplication.js:31)

My project: https://github.com/BarryYan/musicApp

Environment

software version
react-navigation 2.9.3
react-native 0.56.0
node 10.0.0
npm or yarn 6.0.0

react-navigation #4788

[v2.0.2] getNavigationActionCreators isn't a function

In React-Navigation v2, there's no longer an export for getNavigationActionCreators on react-navigation. middleware.js imports this and results in an thrown error.

The fix would be:
import getNavigationActionCreators from 'react-navigation/src/routers/getNavigationActionCreators';

Edit: noticed you were aware of this issue

npm run test error

npm run test (jest) error in a new project (react-native init), after intalled react-navigation-redux-helpers

TypeError: Cannot read property 'init' of undefined

I am using Jest to write unit test cases, Just week ago my test cases was working properly, but from last two days i am getting one error. I havent done any changes, i dont understand why this coming and tried to find solution but didnt get any proper response. Below i have added my error and configuration.

Error

● Test suite failed to run

TypeError: Cannot read property 'init' of undefined
  
  at Object.<anonymous> (node_modules/react-navigation-redux-helpers/src/reducer.js:1:306)
  at Object.<anonymous> (node_modules/react-navigation-redux-helpers/src/middleware.js:1:366)
  at Object.<anonymous> (node_modules/react-navigation-redux-helpers/src/index.js:1:419)

And In my package.json file

 "react": "16.3.1",
 "react-native": "^0.55.4",
 "react-navigation": "^1.5.12",
 "react-navigation-redux-helpers": "^1.0.5",
  "react-redux": "^5.0.7",
   "redux-thunk": "^2.2.0",

I have also added

 "jest": {
    "preset": "react-native",
    "transformIgnorePatterns": [
      "node_modules/(?!react-native|native-base|rn-viewpager|react-navigation-redux-helpers|react-navigation)"
    ]
  }

Please let me know if anybody facing such issues or any one have got any solution to fix this.
Thanks

TypeScript libdef for 2.0

Hello! A new release is coming, and the API should be a bit simpler: https://github.com/react-navigation/react-navigation-redux-helpers/

This necessitates updating the typings. On the Flow side it was a bit complex, since we have a new HOC: https://github.com/react-navigation/react-navigation-redux-helpers/blob/master/src/reduxify-navigator.js

I don't use TypeScript, and am not sure how to type this correctly. Would anybody from the community be able to help with these updates?

addListener() broken with redux + react-navigation-2

If I reduxifyNavigator(), then this.props.navigator.addListener('willFocus', cb) (and other events) won't fire. This can be seen with the following patch to ReduxExample.

Bug

The console messages LoginScreen will focus and LoginScreen will blur won't be displayed to console as expected.

Removing reduxifyNavigator() and using RootNavigator directly triggers the events, so it's clearly a bug on how redux middleware is handling its actions.

Showcase Patch

Apply the following patch to ReduxExample

diff --git a/examples/ReduxExample/src/components/LoginScreen.js b/examples/ReduxExample/src/components/LoginScreen.js
index 1efe17e..e2b55e5 100644
--- a/examples/ReduxExample/src/components/LoginScreen.js
+++ b/examples/ReduxExample/src/components/LoginScreen.js
@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { Component } from 'react';
 import PropTypes from 'prop-types';
 import { Button, StyleSheet, Text, View } from 'react-native';
 
@@ -16,7 +16,7 @@ const styles = StyleSheet.create({
   },
 });
 
-const LoginScreen = ({ navigation }) => (
+const LoginScreenRender = ({ navigation }) => (
   <View style={styles.container}>
     <Text style={styles.welcome}>
       Screen A
@@ -31,6 +31,32 @@ const LoginScreen = ({ navigation }) => (
   </View>
 );
 
+class LoginScreen extends Component {
+  componentDidMount() {
+    this._willFocus = this.props.navigation.addListener('willFocus', () => {
+      console.log('LoginScreen will focus!');
+    });
+    this._willBlur = this.props.navigation.addListener('willBlur', () => {
+      console.log('LoginScreen will blur!');
+    });
+  }
+
+  componentWillUnmount() {
+    if (this._willFocus) {
+      this._willFocus.remove();
+      this._willFocus = null;
+    }
+    if (this._willBlur) {
+      this._willBlur.remove();
+      this._willBlur = null;
+    }
+  }
+
+  render() {
+    return LoginScreenRender(this.props);
+  }
+}
+
 LoginScreen.propTypes = {
   navigation: PropTypes.object.isRequired,
 };

Bad arguments on ReduxifyNavigator

Here are my files :
navigation/index.ts
navigation/routes.ts
navigation/Reducers/index.ts

I have an error into navigation/index.ts on line 23. Sorry, it's in french.
Could you help me to understand what I have to do please ?
Thanks.

L'argument de type 'ComponentType<{ state: NavigationState; dispatch: NavigationDispatch; }>' n'est pas attribuable au paramètre de type 'ComponentType<Matching<{ state: NavigationState; } & DispatchProp, { state: NavigationState; dispatch: NavigationDispatch; }>>'.

Impossible d'assigner le type 'ComponentClass<{ state: NavigationState; dispatch: NavigationDispatch; }, any>' au type 'ComponentType<Matching<{ state: NavigationState; } & DispatchProp, { state: NavigationState; dispatch: NavigationDispatch; }>>'.

Impossible d'assigner le type 'ComponentClass<{ state: NavigationState; dispatch: NavigationDispatch; }, any>' au type 'ComponentClass<Matching<{ state: NavigationState; } & DispatchProp, { state: NavigationState; dispatch: NavigationDispatch; }>, any>'.

Les types de la propriété 'propTypes' sont incompatibles.

Impossible d'assigner le type 'ValidationMap<{ state: NavigationState; dispatch: NavigationDispatch; }> | undefined' au type 'ValidationMap<Matching<{ state: NavigationState; } & DispatchProp, { state: NavigationState; dispatch: NavigationDispatch; }>> | undefined'.

Impossible d'assigner le type 'ValidationMap<{ state: NavigationState; dispatch: NavigationDispatch; }>' au type 'ValidationMap<Matching<{ state: NavigationState; } & DispatchProp, { state: NavigationState; dispatch: NavigationDispatch; }>>'.

Les types de la propriété 'dispatch' sont incompatibles.

Impossible d'assigner le type 'Validator' au type 'Validator<Dispatch>'.

Impossible d'assigner le type 'NavigationDispatch' au type 'Dispatch'. [2345]
const App: React.ComponentType<{state: NavigationState; dispatch: NavigationDispatch;
}>

Stack Navigator reducer not initializing correctly

Current Behavior

I am trying to merge redux with my navigation state. I have a stack navigator that returns a tab navigator. I have followed the new react navigation redux guide, but when I try to import the navigator reducer as part of my combine reducers, it throws me "No reducer provided for key navigation." I tracked the issue down and it appears to be doing things out of order: initial console log, timed out console log.

Expected Behavior

The reducer should initialize with the defined router and not be throwing this error.

How to reproduce

https://gist.github.com/prodigynelson/d05cfed480730be06b381c7385c3e488

Your Environment

software version
react-navigation 1.0.0-beta.19
react-native .50

Flow errors on react-native 0.54.2

Hello,

I am having some flow fails on my project when updating to react-native 0.54.2

Here are the errors :
image

I am using last version : "react-navigation-redux-helpers": "^1.0.3",

nested TabBarNavigator in StackNavigator cause blank screens

Current Behavior

When I navigate between Tabbar screen, the initial screen is loaded properly, mais the other are blank (no render method call)

Here is a demo to reproduce the bug WITH REDUX : https://snack.expo.io/@lmenu/sample-for-tabbar-bug
Here is the same demo WITHOUT REDUX without the bug : https://snack.expo.io/@lmenu/sample-for-tabbar-bug-without-redux

How to reproduce

I red that adding param swipeEnabled: false, animationEnabled: false, lazy: true solve the problem. I did it but have no effect. But if I put swipeEnabled: true or animationEnabled: true, everything is OK.

Here is the structure of my navigation routes.

  • Root StackNavigator (mode modal)
    -- Auth StackNavigator
    -- App TabBarNavigator
    ---- Home StackNavigator
    ---- Notif StackNavigator
    ---- ... Other navigators
    -- ... Other modals

Your Environment

software version
react-navigation 1.2.0
react-native 0.50.4
node 9.4.0
yarn 1.3.2

I'm using Redux with the new library package (react-navigation-redux-helpers)

Thank's in advance.

please publish the index.d.ts

I saw the pull request "#17" already merged and publish the new version 1.0.4, but the problem is v1.0.4 doesn't include the "index.d.ts", so we still have an error when using the typescript, please help to fix it.

SwitchNavigator doesn't work with Redux integration outlined in guide

Hi.

I'm using the exact Redux Integration outlined in the guide found here: https://reactnavigation.org/docs/redux-integration.html

However, when I export a SwitchNavigator (with a StackNavigator as its initial route) as my default Navigator I'm met with the following error:

undefined is not an object (evaluating 'prevState.index')

Here is a Snack reproducing the bug: https://snack.expo.io/Hy643mQtz

Image of stack trace

Any help is much appreciated.

lifecycle events aren't working with redux

Hi all,

While working on our upgrade to the new [email protected] I noticed that the lifecycle events aren't working with react-navigation-redux-helpers. The same code does work without this library.

I'm not sure if this is mentioned in this part of the documentation:
Keep in mind that when a navigator is given a navigation prop, it relinquishes control of its internal state. That means you are now responsible for persisting its state, handling any deep linking, Handling the Hardware Back Button in Android, etc. from Redux integration documentation of react-navigation

Incase it isn't, I created an Expo Snack to reproduce the issue. The snack is using the redux integration and the lifecycle events aren't firing. If you replace <AppWithNavigationState/> with AppNavigator then the lifecycle events do work.

After doing some debugging on my own and digging into the source code of both react-navigation and react-navigation-redux-helpers I figured out that the events and there handlers are registered but never fired. Incase this is a new issue that needs to be fixed I will more then glad to help.

Lifecycle documentation
Expo Snack

Let me know what you people think.

getNavigation is undefined

Hey guys

I'm trying to upgrade my app to react-navigation 2.3.0 and react-navigation-redux-helpers 2.0.1. I'm getting the error _reactNavigation.getNavigation is undefined in line 139 of middleware.js.
Any ideas?

Thanks!
Esteban

Typescript 3 compilation error in index.d.ts

Hi, I've started using this dependency in a brand new project and off the bat I get a compilation error from here as follows:

master ✱ ❯ tsc -v
Version 3.0.1

master ✱ ❯ tsc
node_modules/react-navigation-redux-helpers/index.d.ts:25:71 - error TS2344: Type 'S' does not satisfy the constraint 'Action<any>'.

25   ): React.ComponentType<{ state: NavigationState; dispatch: Dispatch<S> }>;
                                                                         ~

Do you guys know what the problem might be?

I've setup my project with the following dependencies:

{
  "dependencies": {
    "react": "16.4.1",
    "react-native": "0.56.0",
    "react-navigation": "2.11.2",
    "react-navigation-redux-helpers": "2.0.5",
    "react-redux": "5.0.7",
    "redux": "4.0.0",
    "redux-thunk": "2.3.0"
  },
  "devDependencies": {
    "@types/react": "16.4.9",
    "@types/react-native": "0.56.7",
    "@types/react-navigation": "2.0.15",
    "@types/react-redux": "6.0.6",
    "babel-jest": "23.4.2",
    "babel-preset-react-native": "^5",
    "jest": "23.5.0",
    "react-test-renderer": "16.4.1",
    "typescript": "3.0.1"
  },
}

How do I get listeners to work with react-navigation and redux

I am trying to get a listener to work. I need to know when a transition is complete. I am registering a listener like this:

this.props.navigation.addListener('didFocus', (payload) => console.warn('did focus')),

I stepped through the code and I am confused with the following:

function createReduxBoundAddListener(key: string) {
  invariant(
    reduxSubscribers.has(key),
    "Cannot listen for a key that isn't associated with a Redux store. " +
      "First call `createReactNavigationReduxMiddleware` so that we know " +
      "when to trigger your listener."
  );
  return (eventName: string, handler: NavigationEventCallback) => {
    if (eventName !== 'action') {
      return { remove: () => {} };
    }
    const subscribers = reduxSubscribers.get(key);
    invariant(subscribers, `subscribers set should exist for ${key}`);
    subscribers.add(handler);
    return {
      remove: () => {
        subscribers.delete(handler);
      },
    };
  };
}

So according to the createReduxBoundAddListener function, the eventName has to be "action" or addListener does nothing. So I tried "action" and assumed I was suppose to read the eventName from within my handler and then do something. I also am assuming that addListener should only be called once. My handler never gets called as far as I can tell.

What am I missing ?

redux-helper doesn't work with react-navigation 2.3.0

TypeError: navigation.getChildNavigation is not a function

I think it's because createNavigationPropConstructordoesn't use createNavigator from react-navigation, so the created navigation object don't get all needed functions react-navigation expect to be presents.

Nested TabNavigator Screen not rendering the first tab navigate

This is a copy from react-navigation/react-navigation#3604 as suggested by @brentvatne

Current Behavior

I have a the following structure with a nested tab navigator (main navigation) inside a stack navigator (for modals to 'popover'). Once managing the state via redux or mobx the first navigate (via tabbing) in the tab navigator to e.g. 'Tab2' is not rendered. After navigating back and forth it gets rendered. Using the same navigation structure but without redux/mobx works just fine.

export const MainNavigator = TabNavigator({
  Tab1: {screen: createScreen('tab1')},
  Tab2: {screen: createScreen('tab2')},
  Tab3: {screen: createScreen('tab3')}
})

export const AppNavigator = StackNavigator({
  Main: { screen: MainNavigator },
});

Expected Behavior

Use a redux/mobx state management with the same behaviour as plain react navigation.

How to reproduce

Here's a demo on expo:
https://snack.expo.io/@toytonic/react-navigation-nested-tabnavigator-redux

Your Environment

software version
react-navigation 1.2.0 ( or latest master)
react-native 0.52.0
node 8
npm or yarn 1.3.2

Document API

redux + react-navigation needs more docs/tutorials pls

Nested Navigators with redux render twice

Using:

react-navigation: '1.3.2'
react-navigation-redux-helpers: '1.0.2'

On first load, the Home Screen is mounted twice:

App.js

import React, { Component } from 'react';
import { addNavigationHelpers } from 'react-navigation';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';

import RootTab from './navigation/RootTab';
import addListener from './store/middleware';

@connect(state => ({
  navigation: state.navigation,
}))
class App extends Component {
  static propTypes = {
    dispatch: PropTypes.func.isRequired,
    navigation: PropTypes.shape({}).isRequired,
  };
  render() {
    const { dispatch, navigation } = this.props;
    return (
      <RootTab
        navigation={addNavigationHelpers({
          dispatch,
          state: navigation,
          addListener,
        })}
      />
    );
  }
}

middleware.js

import { createReduxBoundAddListener, createReactNavigationReduxMiddleware } from 'react-navigation-redux-helpers';

export const middleware = createReactNavigationReduxMiddleware('root', state => state.navigation);

export default createReduxBoundAddListener('root');

RootTab.js

import { TabNavigator } from 'react-navigation';

import HomeStack from './HomeStack';

import routes from '../constants/routes';

export default TabNavigator(
  {
    [routes.HOME_TAB]: {
      screen: HomeStack,
    },
  },
  {
    initialRouteName: routes.HOME_TAB,
  }
);

HomeStack.js

import { StackNavigator } from 'react-navigation';

import { Home } from '../screens';
import routes from '../constants/routes';

export default StackNavigator(
  {
    [routes.HOME_STACK]: {
      screen: Home,
    },
  },
  {
    initialRouteName: routes.HOME_STACK,
  }
);

Home.js

import React, { Component } from 'react';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import { NavigationActions } from 'react-navigation';
import { Alert } from 'react-native';

import { showAlert } from '../../actions/ui';
import HomeView from './Home.view';
import { LogoHeaderTitle } from '../../components/';
import routes from '../../constants/routes';

@connect(
  ({ alert }) => ({ alert }),
  dispatch => ({
    showAlert: (question, buttons) => dispatch(showAlert(question, buttons)),
  })
)
class HomeScreen extends Component {
  static navigationOptions = () => ({
    headerTitle: <LogoHeaderTitle />,
  });
  static propTypes = {
    navigation: PropTypes.shape({
      dispatch: PropTypes.func,
    }).isRequired,
    showAlert: PropTypes.func.isRequired,
    alert: PropTypes.shape({
      question: PropTypes.string,
      buttons: PropTypes.arrayOf(
        PropTypes.shape({
          label: PropTypes.string,
          onClick: PropTypes.func,
        })
      ),
    }).isRequired,
  };

  componentDidMount() {
    console.log('did mount: HOME');
  }

  componentWillReceiveProps = nextProps => {
    const { question, buttons } = nextProps.alert;
    console.log(this.props);
    if (this.props.alert.question.length === 0 && nextProps.alert.question.length > 0) {
      // Alert.alert('', question, buttons);
    }
  };

  handleAlert = () => {
    const { showAlert, navigation } = this.props;
    showAlert('Question?', [
      {
        text: '1',
        onPress: () => navigation.dispatch(NavigationActions.navigate({ routeName: routes.TEST })),
      },
      {
        text: '2',
        onPress: () => console.log('navigate to 2'),
      },
      {
        text: 'Cancel',
        style: 'cancel',
      },
    ]);
  };

  render() {
    console.log('render');
    return <HomeView onAlert={this.handleAlert} />;
  }
}

export default HomeScreen;

NavReducer.js

import RootTabNavigator from '../navigation/RootTab';
import routes from '../constants/routes';

export const initialState = RootTabNavigator.router.getStateForAction(
  RootTabNavigator.router.getActionForPathAndParams(routes.HOME_TAB)
);

export default (state = initialState, action) => {
  const nextState = RootTabNavigator.router.getStateForAction(action, state);

  return nextState || state;
};

When starting the app, the debugger displays 2 console logs of render and did mount: HOME.

I'm expecting to only render once, as the default React Navigation behaviour, without Redux.

Edit:
Seems that not calling setting state to initialState in the NavReducer fixes this, if that is the issue, please update documentation on Redux Integration on https://reactnavigation.org/docs/redux-integration.html

support react-navigation v3?

Hi,

Just wondering if support for react-navigation v3 (currently in alpha) is planned for this repo?

As mentionned in the doc, there will be no official support for redux in v3. Just wonder if someone has started working on non-official support?

Also, if no support, will a migration path be recommended?

My usecase

I'm the new maintainer of a legacy app, initially based on Ignite, that I migrated to Expo. It extensively uses redux-saga for all api calls and dispatching navigation actions (not my choice). I don't really care about keeping navigation state in Redux, but I don't necessarily want to rewrite all the async/navigation of my app to upgrade to the upcoming v3.

I'm probably not alone in this case, navigating by dispatching redux actions, from a place where the navigation prop is not provided.

possible solution

Just to give some ideas, here is a possible migration path that I envision:

  • Keep Redux and my sagas
  • Use Redux as a simple event bus for navigation actions (like my redux-dispatch-subscribe.
  • create a component that receive navigation prop, attach dispatch listener to redux, and forward redux navigation actions directly to the navigation.dispatch

The idea is to still be able to navigate by dispatching to redux (and thus from sagas), but do not keep navigation state inside redux, and instead forward the actions to the stateful navigation container directly. Hope this makes sense.

Add dependencies to package.json

There is a dependency used in src/reducer.js and not defined in package.json:

import { NavigationActions } from "react-navigation";

I suggest to add the dependency react-navigation to package.json.

There are also a lot of import type rows in different files. I'm not sure whether this kind of dependency should be specified in package.json:

import type {
  NavigationEventCallback,
  NavigationEventPayload,
  NavigationState,
} from 'react-navigation';
import type { Middleware } from 'redux';

import type { NavigationAction, NavigationState } from 'react-navigation';
import type { Reducer } from 'redux';

import type { NavigationContainer, NavigationState } from 'react-navigation';

Jest Test Error "Cannot read property 'init' of undefined"

I am getting the following error trying to test a component that has the following react-navigation import lines:

import { NavigationActions } from 'react-navigation';
import AppWithNavigationState from './src/Navigators/AppNavigator';

image

The error file "reducer.js" looks like this:

import type { NavigationAction, NavigationState } from 'react-navigation';
import type { Reducer } from 'redux';
import type { Navigator, ReducerState } from './types'

import { NavigationActions } from "react-navigation";

const initAction = NavigationActions.init();

function createNavigationReducer(navigator: Navigator): Reducer<*, *> {
  const initialState = navigator.router.getStateForAction(initAction, null);
  return (
    state: ReducerState = initialState,
    action: NavigationAction,
  ): ReducerState => {
    return navigator.router.getStateForAction(action, state);
  };
};

export {
  createNavigationReducer,
  initAction,
};

My only react-navigation-redux-helpers import is in a file that contains the following code and builds my navigation middleware.

import {
    createReactNavigationReduxMiddleware,
    createReduxBoundAddListener,
  } from 'react-navigation-redux-helpers';
  
  const reactNavigationMiddleware = createReactNavigationReduxMiddleware(
    "root",
    state => state.nav,
  );
  const addListener = createReduxBoundAddListener("root");
  
  export {
    reactNavigationMiddleware,
    addListener,
  };

I've added the Jest configuration information referenced in #9, and the "jest" configuration in my package.json looks like this:

"jest": {
    "preset": "jest-expo",
    "testRegex": "__tests__/(.*).test.js$",
    "setupFiles": [
      "./__tests__/setup.js"
    ],
    "moduleFileExtensions": [
      "js",
      "jsx"
    ],
    "moduleDirectories": [
      "node_modules",
      "bower_components",
      "shared"
    ],
    "moduleNameMapper": {
      "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/__mocks__/fileMock.js",
      "\\.(css|less)$": "<rootDir>/__mocks__/styleMock.js",
      "\\./datepicker$": "<rootDir>/node_modules/tcomb-form-native/lib/templates/bootstrap/datepicker.ios.js",
      "\\./select$": "<rootDir>/node_modules/tcomb-form-native/lib/templates/bootstrap/select.ios.js"
    },
    "unmockedModulePathPatterns": [
      "node_modules/react/",
      "node_modules/enzyme/"
    ],
    "transform": {
      "^.+\\.jsx?$": "babel-jest",
      "\\.(png)$": "<rootDir>/__mocks__/fileMock.js"
    },
    "transformIgnorePatterns": [
      "node_modules/(?!react-navigation-redux-helpers|react-native|expo|tcomb-form-native|react-navigation)"
    ]
  }

Version information:
"react-navigation": "1.5.11",
"react-navigation-redux-helpers": "^1.0.5",

Typescript definitions

Probably related with #3, i made .d.ts for this repo. Should i add it here or into DefinitelyTyped? Or you'll do it by yourselves?

How to wrap reduxifyNavigator into a component

Hi everyone,
I am using
"react-navigation": "^2.3.1",
"react-navigation-redux-helpers": "^2.0.2"

With reduxifyNavigator, I don't know where to add Handling the Hardware Back Button in Android
I try wrap reduxifyNavigator into a compenet like below but it not work:

`
import {
createStackNavigator,
NavigationActions
} from 'react-navigation';
import {
createStore,
applyMiddleware,
combineReducers,
} from 'redux';
import { BackHandler } from "react-native";
import {
reduxifyNavigator,
createReactNavigationReduxMiddleware,
createNavigationReducer,
} from 'react-navigation-redux-helpers';
import { Provider, connect } from 'react-redux';
import React from 'react';

const AppNavigator = createStackNavigator(AppRouteConfigs);

const navReducer = createNavigationReducer(AppNavigator);
const appReducer = combineReducers({
nav: navReducer,
...
});

// Note: createReactNavigationReduxMiddleware must be run before reduxifyNavigator
const middleware = createReactNavigationReduxMiddleware(
"root",
state => state.nav,
);

const App = reduxifyNavigator(AppNavigator, "root");
class ReduxNavigation extends React.Component {
componentDidMount() {
BackHandler.addEventListener("hardwareBackPress", this.onBackPress);
}

componentWillUnmount() {
BackHandler.removeEventListener("hardwareBackPress", this.onBackPress);
}

onBackPress = () => {
const { dispatch, nav } = this.props;
if (nav.index === 0) {
return false;
}

dispatch(NavigationActions.back());
return true;

};

render() {
/* more setup code here! this is not a runnable snippet */
return ;
}
}
const mapStateToProps = (state) => ({
state: state.nav,
});
const AppWithNavigationState = connect(mapStateToProps)(ReduxNavigation);

const store = createStore(
appReducer,
applyMiddleware(middleware),
);

class Root extends React.Component {
render() {
return (



);
}
}
`

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.