Skip to content

Instantly share code, notes, and snippets.

@machadogj
Created May 10, 2018 02:17
Show Gist options
  • Save machadogj/e266fdc36076492e78f0ad5516848938 to your computer and use it in GitHub Desktop.
Save machadogj/e266fdc36076492e78f0ad5516848938 to your computer and use it in GitHub Desktop.
State based navigation PoC
import React, { Component, PropTypes} from 'react';
import { View } from 'react-native';
import {
Container,
Title,
Message,
Button
} from '../components';
import { connect } from 'react-redux';
import { actions as mainActions} from '../store/models/main';
import { selectors as mainSelectors } from '../store/models/main';
const { addCigarette } = mainActions;
class Home extends Component {
static propTypes = {
cardToken: PropTypes.string,
dailyCigarettes: PropTypes.number.isRequired,
todaysCigarettes: PropTypes.number.isRequired,
onAdd: PropTypes.func.isRequired
};
constructor(props) {
super(props);
this.state = {
};
}
handleSubmit = () => {
let { dailyCigarettes, todaysCigarettes, cardToken } = this.props;
let availableCigarettes = dailyCigarettes - todaysCigarettes;
this.props.onAdd(availableCigarettes, cardToken);
}
handleAddCreditCard = () => {
this.props.navigator.push({key: 'credit-card'});
}
render() {
let { dailyCigarettes, todaysCigarettes, cardToken } = this.props;
let availableCigarettes = dailyCigarettes - todaysCigarettes;
let nextCigaretteCost = availableCigarettes > 0 ? 0 : Math.pow(2, Math.abs(availableCigarettes));
return (
<Container>
<View style={ {flex: 1} }>
<Title text={ 'Stay strong!' }/>
<Message
text={ `Daily Cigarettes: ${this.props.dailyCigarettes}` }
/>
<Message
text={ `Today's Cigarettes: ${this.props.todaysCigarettes}` }
/>
<Message
text={ `Available Cigarettes: ${this.props.dailyCigarettes - this.props.todaysCigarettes}` }
/>
<Message
text={ `Your next cigarette will cost you!` }
/>
{ !nextCigaretteCost ? null : (
<Message
style={ {color: 'red'} }
text={ `When you tap on the button below, you will be charged USD${nextCigaretteCost}.00 to your credit card. So think twice before you smoke that next cigarette!` }
/>
)}
</View>
<Message
text="Every time you smoke a cigarette, tap on the button below!"
/>
{
nextCigaretteCost > 1 && !cardToken ?
<Button text="Add Credit Card" onPress={ this.handleAddCreditCard }/>
:
<Button text="Add Cigarette!" onPress={ this.handleSubmit }/>
}
</Container>
);
}
}
export default connect(
(state) => ({
dailyCigarettes: state.get('config').toJS().dailyCigarettes,
todaysCigarettes: mainSelectors.todaysCigarettes(state),
cardToken: state.get('config').toJS().cardToken
}), //eslint-disable-line
(dispatch, props) => ({
onAdd: (/*availableCigarettes, cardToken*/) => {
// let { navigator } = props;
// let needToCharge = availableCigarettes <= 0;
// console.log(availableCigarettes, needToCharge, cardToken);
// if (needToCharge && !cardToken) {
// navigator.push({key:'credit-card'})
// }
dispatch(addCigarette())
}
})
)(Home);
import React, { Component } from 'react';
import {
Navigator
} from 'react-native';
import Init from './scenes/init';
import Tour from './scenes/tour';
import Monthly from './scenes/monthly';
import Daily from './scenes/dailyCigarettes';
import Home from './scenes/home';
import Email from './scenes/email';
import CreditCard from './scenes/creditCard';
import store from './store';
import { connect } from 'react-redux';
import { actions as appActions} from './store/models/app';
import { selectors as mainSelectors } from './store/models/main';
const routes = {
'init': Init,
'tour': Tour,
'monthly': Monthly,
'daily': Daily,
'home': Home,
'email': Email,
'credit-card': CreditCard
};
const transitionMatrix = {
init: [{
condition: (props) => {
let onboarded = props.config.monthly && props.config.dailyCigarettes;
return props.app.initialized && !onboarded
},
route: { key: 'tour' }
}, {
condition: (props) => props.app.initialized,
route: { key: 'home', transition: 'resetTo' }
}],
home: [{
condition: (props) => {
let { needToCharge } = props;
let { email } = props.config;
return needToCharge && !email;
},
route: { key: 'email' }
}, {
condition: (props) => {
let { needToCharge } = props;
let { cardId } = props.config;
return needToCharge && !cardId;
},
route: { key: 'credit-card' }
}]
}
class Router extends Component {
componentDidMount() {
this.navigator.navigationContext.addListener('didfocus', (event) => {
this.onDidFocus();
});
store.dispatch(appActions.init());
}
componentDidUpdate(prevProps, prevState) {
this.onDidFocus();
}
onDidFocus = () => {
let currentRoutes = this.navigator.getCurrentRoutes();
console.log('onDidFocus', currentRoutes.map(r => r.key));
let currentRoute = currentRoutes[currentRoutes.length-1];
let rules = transitionMatrix[currentRoute.key];
if (!rules) {
console.log('currentRoute.key has no router rules!', currentRoute.key);
return;
}
for (let rule of rules) {
if (rule.condition(this.props)) {
this.navigator[rule.transition || 'push'](rule.route);
break; //only support one rule at a time (?)
}
}
}
_renderScene(route, navigator) {
const Scene = routes[route.key];
return <Scene navigator={navigator} {...route.data}/>
}
render () {
return (
<Navigator
ref={ n => this.navigator = n }
initialRoute={{ key: 'init' }}
renderScene={this._renderScene}
/>
);
}
}
export default connect(
(state) => ({
app: state.get('app').toJS(),
config: state.get('config').toJS(),
needToCharge: mainSelectors.needToCharge(state)
}),
(dispatch) => ({})
)(Router)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment