I'm trying to use react-navigation with redux (and react-native-meteor). This is my current setup which follows react-navigation advice. My entry point file is below:
src/index.js
import React from 'react';
import Meteor, { createContainer } from 'react-native-meteor';
import { Loading } from './components/common';
import { addNavigationHelpers } from 'react-navigation';
import { Provider, connect } from "react-redux";
import getStore from "./store";
import Routes from "./routes";
import * as actions from './actions';
//connect to meteor
Meteor.connect('ws://localhost:3000/websocket');
//create nav reducer
const navReducer = (state, action) => {
const newState = Routes.router.getStateForAction(action, state);
return newState || state;
};
const mapStateToProps = (state) => {
return {
nav: state.nav,
bizStages: state.bizStages,
categories: state.categories,
selectedLocation: state.selectedLocation
}
};
// connect Routes Component with redux, remember you need babelrc with "transform-decorators-legacy" to use decorators
@connect(mapStateToProps)
class RoutesWithNavigationState extends React.Component {
render() {
return (
<Routes navigation={addNavigationHelpers({ ...this.props, state: this.props.nav })} />
);
}
}
// create store and then rest of this file is similar to setup in Spencer's react-native-meteor-boilerplace: https://github.com/spencercarli/react-native-meteor-boilerplate
const store = getStore(navReducer);
const App = (props) => {
return (
<Provider store={store}>
{props.status.connected === false || props.loggingIn
? <Loading {...props} />
: <RoutesWithNavigationState {...props} />
}
</Provider>
);
}
App.propTypes = {
status: React.PropTypes.object,
user: React.PropTypes.object,
loggingIn: React.PropTypes.bool,
};
export default createContainer(() => {
return {
status: Meteor.status(),
user: Meteor.user(),
loggingIn: Meteor.loggingIn(),
};
}, App);
store.js
import { createStore, applyMiddleware } from "redux";
import thunk from "redux-thunk";
import getRootReducer from "./reducers";
const getStore = (navReducer) => {
const store = createStore( getRootReducer(navReducer), undefined, applyMiddleware(thunk) );
return store;
}
export default getStore;
There is no login right now. My initial screen is just a list (<MainScreen />, which you can see below). At the top of the page there is a picker (<LocationSelector />) that allows you to select a location. It runs a redux action. That action runs correctly, and <RoutesWithNavigationState /> from src/index.js reruns with new props, but my createContainer that wraps MainScreen (see below) is not re-run...
So I'm not 100% sure how to set this up. It'd be great if all actions and redux store values can just be dropped down via the navigation prop instead of sprinkling @connect everywhere I could just have it in src/index.js... but child components are not updating when properties on the navigation object change.
Should I use @connect on createContainer to get it to work? am I just missing some redux-related thing? Its getting a little crazy between all these HOCs...(1) hoistNonReactStatic so I can use static in my class, (2) createContainer from react-native-meteor and now I'm wondering if I have to wrap it again in @connect so that I have access to the redux variables in createContainer?
import React from 'react';
import Meteor, { createContainer } from 'react-native-meteor';
import { Image, TouchableHighlight, View, ListView } from 'react-native';
import { Container, Content, Grid, Picker, Col, Card, CardItem, Left, Body, Text, Button, Icon, Right } from 'native-base';
import hoistNonReactStatic from 'hoist-non-react-statics';
import { Loading } from '../../components/common';
import { connect } from "react-redux";
import * as actions from '../../actions';
import { ResourceCard from './ResourceCard'
import { LocationSelector } from './LocationSelector'
class MainScreen extends React.Component {
static navigationOptions = {
title: 'Home',
tabBar: { label: 'Home' }
};
render(){
let { navigation, items, resourceItemsReady } = this.props;
let { navigate, dispatch } = navigation;
let ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
if (!resourceItemsReady) {
return (
<Container style={{backgroundColor: '#f5f5f5'}}>
<Loading />
</Container>
);
}
return (
<Container style={{backgroundColor: '#f5f5f5'}}>
<Content style={{padding: 10}}>
<Text>Show me resources near...</Text>
<LocationSelector
selectLocation={(value)=>dispatch({ type: 'select_location', payload: value})}
/>
<ListView
dataSource={ds.cloneWithRows(items)}
renderRow={(rowData) => <ResourceCard item={rowData} navigation={navigation} />}
/>
</Content>
</Container>
);
}
}
const container = createContainer(params => {
let resourceItemsSub = Meteor.subscribe('ResourceItems.searchResults'); //this is where I would like to pass in different parameters like categories, search terms, etc
return {
resourceItemsReady: resourceItemsSub.ready(),
items: Meteor.collection('ResourceItems').find(),
navigation: params.navigation
};
}, MainScreen);
export default hoistNonReactStatic(container, MainScreen);
I'm trying to use react-navigation with redux (and react-native-meteor). This is my current setup which follows react-navigation advice. My entry point file is below:
src/index.js
store.js
reducers/index.js
There is no login right now. My initial screen is just a list (
<MainScreen />
, which you can see below). At the top of the page there is a picker (<LocationSelector />
) that allows you to select a location. It runs a redux action. That action runs correctly, and<RoutesWithNavigationState />
fromsrc/index.js
reruns with new props, but my createContainer that wraps MainScreen (see below) is not re-run...So I'm not 100% sure how to set this up. It'd be great if all actions and redux store values can just be dropped down via the navigation prop instead of sprinkling @connect everywhere I could just have it in
src/index.js
... but child components are not updating when properties on the navigation object change.Should I use @connect on createContainer to get it to work? am I just missing some redux-related thing? Its getting a little crazy between all these HOCs...(1) hoistNonReactStatic so I can use static in my class, (2) createContainer from react-native-meteor and now I'm wondering if I have to wrap it again in @connect so that I have access to the redux variables in createContainer?
Seems maybe similar to this disucssion: https://github.com/inProgress-team/react-native-meteor/issues/84