├── README.md ├── Section 1 ├── 1.2 │ └── App.js └── 1.3 │ └── App.js ├── Section 2 ├── 2.3 │ └── App.js └── 2.4 │ ├── App.js │ ├── AppStyle.js │ └── styles │ ├── buttons.js │ ├── colors.js │ ├── index.js │ ├── metrics.js │ └── typography.js ├── Section 3 ├── 3.1 │ └── MainActivity.java ├── 3.2 │ ├── App.js │ ├── Components │ │ ├── FancyButton.js │ │ ├── FancyInput.js │ │ └── Styles │ │ │ └── AppStyle.js │ └── Screens │ │ ├── DetailScreen.js │ │ ├── HomeScreen.js │ │ └── SignUpScreen.js └── 3.3 │ ├── App.js │ └── Navigation │ ├── RootNavigator.js │ ├── StackNav.js │ └── TabNav.js ├── Section 4 ├── 4.2 │ ├── HOCBUG.jsx │ └── section4code.jsx └── 4.3 │ ├── FancyButton.js │ ├── WithNav.js │ └── WithStyle.js ├── Section 5 ├── 5.1 │ └── renderPropEx.js ├── 5.2 │ ├── FancyButton.js │ ├── WithStyle.js │ └── componentComposition.jsx └── 5.3 │ ├── FancyInput.js │ ├── HomeScreen.js │ └── ValidationMessage.js ├── Section 6 ├── 6.1 │ ├── SignUpScreen.js │ └── children.jsx ├── 6.2 │ └── SignUpScreen.js └── 6.3 │ ├── CommonForm.js │ ├── DetailScreen.js │ ├── EmailInput.js │ ├── FancyInput.js │ ├── HomeScreen.js │ ├── PasswordInput.js │ ├── SignUpScreen.js │ └── UserInput.js ├── Section 7 ├── 7.2 │ ├── Contexts │ │ └── EntryContext.js │ ├── CustomText.js │ ├── CustomView.js │ ├── SignUpScreen.js │ └── componentComp.js └── 7.3 │ ├── CommonForm.js │ ├── SignUpScreen.js │ └── UserContext.js └── Section 8 ├── 8.1 ├── complexComponent.js └── customHook.js ├── 8.2 ├── HookScreen.js ├── SignUpScreen.js ├── StackNav.js ├── sideEffect.js ├── useContext.js ├── useEffect.js └── useState.js └── 8.3 ├── EmailInput.js ├── FancyInput.js ├── HomeScreen.js ├── HookScreen.js ├── PasswordInput.js ├── UseScreenTimer.js └── UserInput.js /README.md: -------------------------------------------------------------------------------- 1 | # React Native Design Patterns [Video] 2 | This is the code repository for [React Native Design Patterns [Video]](https://www.packtpub.com/mobile/react-native-design-patterns-video), published by [Packt](https://www.packtpub.com/?utm_source=github). It contains all the supporting project files necessary to work through the video course from start to finish. 3 | ## About the Video Course 4 | Design Patterns are time-tested solutions that can be utilized as guidelines in your current work. Utilizing Design Patterns enhances code readability, improves the scalability of your applications, and defines a common language with other developers. 5 | In this course, you will develop an understanding of different Design Patterns and understand why a specific pattern was created, and how it should be implemented. By working on practical examples, you will learn how mobile development in React Native should be performed in a reusable way. 6 | By the end of the course, you will be adept at utilizing the best solution for a given problem in your next React Native application. 7 | 8 | 9 |

What You Will Learn

10 |
11 |
20 | 21 | ## Instructions and Navigation 22 | ### Assumed Knowledge 23 | This course is for React Native developers who want to improve their skills to become more efficient and write better code with design patterns. 24 | 25 | ### Technical Requirements 26 | Minimum Hardware Requirements 27 | 28 | For successful completion of this course, students will require the computer systems with at least the following: 29 | 30 | · OS: Windows/Mac OS 31 | 32 | · Processor: i5 or equivalent 33 | 34 | · Memory: 8Gb or more 35 | 36 | · Storage: 128 Gb or more 37 | 38 | Recommended Hardware Requirements 39 | 40 | For an optimal experience with hands-on labs and other practical activities, we recommend the following configuration: 41 | 42 | · OS: Mac OS 43 | 44 | · Processor: i7 45 | 46 | · Memory: 16 GB 47 | 48 | · Storage: 256 GB (SSD) 49 | 50 | Software Requirements 51 | 52 | · OS: Window/Mac/Linux 53 | 54 | · Browser: Chrome 55 | 56 | · Code Editor: Visual Studio Code 57 | 58 | · Others: Node JS , NPM , Android Studio , XCode and Android SDK 59 | 60 | Node JS :https://nodejs.org/en/download/ 61 | 62 | Android Studio : https://developer.android.com/studio/install.html 63 | 64 | VS Code : https://code.visualstudio.com/ 65 | 66 | ## Related Products 67 | * [React Native in 7 Steps [Video]](https://www.packtpub.com/application-development/cisco-voice-solutions-medium-large-enterprise-mle-cucm-video?utm_source=github&utm_medium=repository&utm_campaign=9781788476263) 68 | 69 | 70 | -------------------------------------------------------------------------------- /Section 1/1.2/App.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { 3 | StyleSheet, 4 | Text, 5 | View, 6 | TextInput, 7 | Dimensions, 8 | TouchableOpacity 9 | } from 'react-native'; 10 | 11 | const { width } = Dimensions.get('screen'); 12 | export default class App extends Component { 13 | constructor() { 14 | super(); 15 | this.state = { 16 | isCurrentUser: false, 17 | user: '', 18 | password: '', 19 | email: '' 20 | }; 21 | } 22 | render() { 23 | return ( 24 | 25 | username 26 | this.setState({ user })} 29 | value={this.state.user} 30 | /> 31 | password 32 | this.setState({ password })} 35 | value={this.state.password} 36 | /> 37 | {this.state.isCurrentUser ? ( 38 | 39 | Log in 40 | 41 | ) : ( 42 | 43 | email 44 | this.setState({ email })} 47 | value={this.state.email} 48 | /> 49 | 50 | Sign up 51 | 52 | 53 | )} 54 | 55 | ); 56 | } 57 | } 58 | 59 | const styles = StyleSheet.create({ 60 | container: { 61 | flex: 1, 62 | justifyContent: 'center', 63 | alignItems: 'flex-start', 64 | backgroundColor: '#F5FCFF' 65 | }, 66 | label: { 67 | fontSize: 20, 68 | alignItems: 'center', 69 | textAlign: 'center', 70 | margin: 10 71 | }, 72 | input: { 73 | borderColor: 'gray', 74 | borderWidth: 1, 75 | width, 76 | height: 45 77 | }, 78 | fancyButton: { 79 | marginTop: 10, 80 | backgroundColor: 'lightblue', 81 | borderBottomRightRadius: 4, 82 | width, 83 | borderWidth: 1, 84 | borderColor: 'gray' 85 | } 86 | }); 87 | -------------------------------------------------------------------------------- /Section 1/1.3/App.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { 3 | StyleSheet, 4 | Text, 5 | View, 6 | TextInput, 7 | Dimensions, 8 | TouchableOpacity 9 | } from 'react-native'; 10 | 11 | const { width } = Dimensions.get('screen'); 12 | 13 | const FancyButton = props => { 14 | return ( 15 | props.setItem([props.item],props.value)}> 18 | {props.text} 19 | 20 | ) 21 | } 22 | 23 | const FancyInput = props => { 24 | return ( 25 | 26 | {props.item} 27 | props.setItem([props.item],value)} 30 | value={props.value} 31 | /> 32 | 33 | ); 34 | } 35 | 36 | class Container extends Component { 37 | constructor() { 38 | super(); 39 | this.state = { 40 | isCurrentUser: false, 41 | user: '', 42 | password: '', 43 | email: '' 44 | }; 45 | } 46 | 47 | setItem(key, value) { 48 | this.setState({ [key]: value }) 49 | } 50 | 51 | render() { 52 | return ( 53 | 54 | 55 | 56 | 57 | 58 | 59 | {this.state.isCurrentUser ? : ( 60 | 61 | 62 | 63 | 64 | 65 | )} 66 | 67 | ); 68 | } 69 | } 70 | 71 | export default class App extends Component { 72 | 73 | render () { 74 | return 75 | } 76 | 77 | } 78 | 79 | const styles = StyleSheet.create({ 80 | container: { 81 | flex: 1, 82 | justifyContent: 'center', 83 | alignItems: 'flex-start', 84 | backgroundColor: '#F5FCFF' 85 | }, 86 | label: { 87 | fontSize: 20, 88 | alignItems: 'center', 89 | textAlign: 'center', 90 | margin: 10 91 | }, 92 | input: { 93 | borderColor: 'gray', 94 | borderWidth: 1, 95 | width, 96 | height: 45 97 | }, 98 | fancyButton: { 99 | marginTop: 10, 100 | backgroundColor: 'lightblue', 101 | borderBottomRightRadius: 4, 102 | width, 103 | borderWidth: 1, 104 | borderColor: 'gray' 105 | } 106 | }); 107 | -------------------------------------------------------------------------------- /Section 2/2.3/App.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { 3 | StyleSheet, 4 | Text, 5 | View, 6 | TextInput, 7 | Dimensions, 8 | TouchableOpacity 9 | } from 'react-native'; 10 | 11 | const { width } = Dimensions.get('screen'); 12 | 13 | const FancyButton = props => { 14 | return ( 15 | props.setItem([props.item], props.value)}> 18 | {props.text} 19 | 20 | ) 21 | } 22 | 23 | const FancyInput = props => { 24 | return ( 25 | 26 | {props.item} 27 | props.setItem([props.item], value)} 30 | value={props.value} 31 | > 32 | 33 | ) 34 | } 35 | 36 | class Container extends Component { 37 | constructor() { 38 | super(); 39 | this.state = { 40 | isCurrentUser: false, 41 | user: '', 42 | password: '', 43 | email: '' 44 | }; 45 | } 46 | 47 | setItem(key,value) { 48 | this.setState({ [key]: value }) 49 | } 50 | 51 | render() { 52 | return ( 53 | 54 | 57 | 58 | 61 | 62 | {this.state.isCurrentUser ? : ( 63 | 64 | 68 | 69 | 73 | 74 | )} 75 | 76 | ); 77 | } 78 | } 79 | 80 | export default class App extends Component { 81 | render () { 82 | return 83 | } 84 | } 85 | 86 | const styles = StyleSheet.create({ 87 | container: { 88 | flex: 1, 89 | justifyContent: 'center', 90 | alignItems: 'flex-start', 91 | backgroundColor: '#F5FCFF' 92 | }, 93 | label: { 94 | fontSize: 20, 95 | alignItems: 'center', 96 | textAlign: 'center', 97 | margin: 10 98 | }, 99 | input: { 100 | borderColor: 'gray', 101 | borderWidth: 1, 102 | width, 103 | height: 45 104 | }, 105 | fancyButton: { 106 | marginTop: 10, 107 | backgroundColor: 'lightblue', 108 | borderBottomRightRadius: 4, 109 | width, 110 | borderWidth: 1, 111 | borderColor: 'gray' 112 | }, 113 | loginButton: { 114 | backgroundColor: 'gray', 115 | borderColor: 'lightblue', 116 | borderBottomLeftRadius: 4 117 | } 118 | }); 119 | -------------------------------------------------------------------------------- /Section 2/2.4/App.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { Text, View, TextInput, TouchableOpacity } from 'react-native'; 3 | import styles from './AppStyle'; 4 | 5 | 6 | const FancyButton = props => { 7 | return ( 8 | props.setItem([props.item], props.value)}> 11 | {props.text} 12 | 13 | ) 14 | } 15 | 16 | const FancyInput = props => { 17 | return ( 18 | 19 | {props.item} 20 | props.setItem([props.item], value)} 23 | value={props.value} 24 | > 25 | 26 | ) 27 | } 28 | 29 | class Container extends Component { 30 | constructor() { 31 | super(); 32 | this.state = { 33 | isCurrentUser: false, 34 | user: '', 35 | password: '', 36 | email: '' 37 | }; 38 | } 39 | 40 | setItem(key,value) { 41 | this.setState({ [key]: value }) 42 | } 43 | 44 | render() { 45 | 46 | return ( 47 | 48 | 51 | 52 | 55 | 56 | {this.state.isCurrentUser ? : ( 57 | 58 | 62 | 63 | 67 | 68 | )} 69 | 70 | ); 71 | } 72 | } 73 | 74 | export default class App extends Component { 75 | render () { 76 | return 77 | } 78 | } 79 | 80 | -------------------------------------------------------------------------------- /Section 2/2.4/AppStyle.js: -------------------------------------------------------------------------------- 1 | import { StyleSheet } from 'react-native'; 2 | import { Buttons, Colors, Metrics } from './styles'; 3 | 4 | export default StyleSheet.create({ 5 | container: { 6 | flex: 1, 7 | justifyContent: 'center', 8 | alignItems: 'flex-start', 9 | backgroundColor: Colors.background 10 | }, 11 | label: { 12 | fontSize: 20, 13 | alignItems: 'center', 14 | textAlign: 'center', 15 | margin: 10 16 | }, 17 | input: { 18 | borderColor: Colors.commonBorderColor, 19 | borderWidth: 1, 20 | width: Metrics.screenWidth, 21 | height: 45 22 | }, 23 | fancyButton: { 24 | ...Buttons.commonButton, 25 | backgroundColor: Colors.buttonColor, 26 | borderColor: Colors.commonBorderColor 27 | }, 28 | loginButton: { 29 | ...Buttons.commonButton, 30 | backgroundColor: 'gray', 31 | borderColor: 'lightblue' 32 | } 33 | }); 34 | -------------------------------------------------------------------------------- /Section 2/2.4/styles/buttons.js: -------------------------------------------------------------------------------- 1 | import {Dimensions, Platform} from 'react-native'; 2 | 3 | const { width, height } = Dimensions.get('window'); 4 | 5 | const buttons = { 6 | commonButton : { 7 | width, 8 | marginTop: 10, 9 | borderBottomRightRadius: 4, 10 | borderWidth: 1, 11 | borderBottomLeftRadius: 4 12 | } 13 | }; 14 | 15 | export default buttons; 16 | -------------------------------------------------------------------------------- /Section 2/2.4/styles/colors.js: -------------------------------------------------------------------------------- 1 | const Colors = { 2 | background: '#F5FCFF', 3 | commonBorderColor: 'gray', 4 | buttonColor: 'lightblue' 5 | }; 6 | 7 | export default Colors; -------------------------------------------------------------------------------- /Section 2/2.4/styles/index.js: -------------------------------------------------------------------------------- 1 | import Buttons from './buttons' 2 | import Colors from './colors'; 3 | import Metrics from './metrics'; 4 | import Typography from './typography'; 5 | 6 | export { Typography, Metrics, Colors, Buttons }; -------------------------------------------------------------------------------- /Section 2/2.4/styles/metrics.js: -------------------------------------------------------------------------------- 1 | import {Dimensions, Platform} from 'react-native'; 2 | 3 | const { width, height } = Dimensions.get('window'); 4 | 5 | const metrics = { 6 | screenWidth: width < height ? width : height, 7 | screenHeight: width < height ? height : width 8 | }; 9 | 10 | export default metrics; 11 | -------------------------------------------------------------------------------- /Section 2/2.4/styles/typography.js: -------------------------------------------------------------------------------- 1 | 2 | const size = { 3 | regular: 16 4 | } 5 | 6 | const style = { 7 | normal: { 8 | fontSize: size.regular 9 | } 10 | } 11 | 12 | export default { 13 | size, 14 | style 15 | } 16 | -------------------------------------------------------------------------------- /Section 3/3.1/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.pattern; 2 | 3 | import com.facebook.react.ReactActivity; 4 | import com.facebook.react.ReactActivityDelegate; 5 | import com.facebook.react.ReactRootView; 6 | import com.swmansion.gesturehandler.react.RNGestureHandlerEnabledRootView; 7 | 8 | 9 | public class MainActivity extends ReactActivity { 10 | 11 | /** 12 | * Returns the name of the main component registered from JavaScript. 13 | * This is used to schedule rendering of the component. 14 | */ 15 | @Override 16 | protected String getMainComponentName() { 17 | return "pattern"; 18 | } 19 | @Override 20 | protected ReactActivityDelegate createReactActivityDelegate() { 21 | return new ReactActivityDelegate(this, getMainComponentName()) { 22 | @Override 23 | protected ReactRootView createRootView() { 24 | return new RNGestureHandlerEnabledRootView(MainActivity.this); 25 | } 26 | }; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Section 3/3.2/App.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { createStackNavigator, createAppContainer, createBottomTabNavigator, createDrawerNavigator } from 'react-navigation'; 3 | import HomeScreen from './Screens/HomeScreen'; 4 | import DetailScreen from './Screens/DetailScreen'; 5 | import SignUpScreen from './Screens/SignUpScreen'; 6 | 7 | 8 | const RootNavigator = createDrawerNavigator( 9 | { 10 | Home: { 11 | screen: HomeScreen, 12 | }, 13 | SignUp: { 14 | screen: SignUpScreen 15 | }, 16 | Detail: { 17 | screen: DetailScreen, 18 | }, 19 | }, 20 | { 21 | initialRouteName: 'SignUp', 22 | headerMode: 'none', 23 | } 24 | ); 25 | 26 | const AppContainer = createAppContainer(RootNavigator); 27 | 28 | export default class App extends Component { 29 | render() { 30 | return ; 31 | } 32 | } -------------------------------------------------------------------------------- /Section 3/3.2/Components/FancyButton.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Text, TouchableOpacity } from 'react-native'; 3 | import styles from './Styles/AppStyle'; 4 | 5 | export const FancyButton = props => { 6 | return ( 7 | props.navigation.navigate(props.route) : 11 | () => props.navigation.goBack() 12 | } 13 | style={(props.text === 'Log in') ? 14 | [styles.fancyButton, styles.loginButton] : 15 | styles.fancyButton}> 16 | {props.text} 17 | 18 | ); 19 | }; 20 | -------------------------------------------------------------------------------- /Section 3/3.2/Components/FancyInput.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Text, TextInput } from "react-native"; 3 | import styles from "./Styles/AppStyle"; 4 | 5 | export const FancyInput = props => { 6 | return ( 7 | 8 | {props.item} 9 | props.setItem([props.item], value)} 12 | value={props.value} 13 | /> 14 | 15 | ); 16 | }; 17 | -------------------------------------------------------------------------------- /Section 3/3.2/Components/Styles/AppStyle.js: -------------------------------------------------------------------------------- 1 | import { StyleSheet } from 'react-native'; 2 | import { Buttons, Colors, Metrics } from '../../Styles'; 3 | 4 | export default StyleSheet.create({ 5 | container: { 6 | flex: 1, 7 | justifyContent: 'center', 8 | alignItems: 'flex-start', 9 | backgroundColor: Colors.background 10 | }, 11 | label: { 12 | fontSize: 20, 13 | alignItems: 'center', 14 | textAlign: 'center', 15 | margin: 10 16 | }, 17 | input: { 18 | borderColor: Colors.commonBorderColor, 19 | borderWidth: 1, 20 | width: Metrics.screenWidth, 21 | height: 45 22 | }, 23 | fancyButton: { 24 | ...Buttons.commonButton, 25 | backgroundColor: Colors.buttonColor, 26 | borderColor: Colors.commonBorderColor 27 | }, 28 | loginButton: { 29 | ...Buttons.commonButton, 30 | backgroundColor: 'gray', 31 | borderColor: 'lightblue' 32 | } 33 | }); 34 | -------------------------------------------------------------------------------- /Section 3/3.2/Screens/DetailScreen.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from "react"; 2 | import { View, Text } from 'react-native'; 3 | import { FancyButton } from "../Components/FancyButton"; 4 | import styles from "../Components/Styles/AppStyle"; 5 | 6 | export default class DetailScreen extends Component { 7 | render() { 8 | return ( 9 | 10 | Welcome to the Details 11 | 14 | 15 | ); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Section 3/3.2/Screens/HomeScreen.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { View } from 'react-native'; 3 | import styles from '../Components/Styles/AppStyle'; 4 | import { FancyButton } from "../Components/FancyButton"; 5 | import { FancyInput } from "../Components/FancyInput"; 6 | 7 | export default class HomeScreen extends Component { 8 | constructor() { 9 | super(); 10 | this.state = { 11 | user: '', 12 | password: '' 13 | }; 14 | } 15 | setItem(key, value) { 16 | this.setState({ [key]: value }); 17 | } 18 | 19 | render() { 20 | return ( 21 | 22 | 23 | 27 | 28 | 32 | 33 | 37 | 38 | 39 | ); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Section 3/3.2/Screens/SignUpScreen.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from "react"; 2 | import { View } from "react-native"; 3 | import styles from "../Components/Styles/AppStyle"; 4 | import { FancyButton } from "../Components/FancyButton"; 5 | import { FancyInput } from "../Components/FancyInput"; 6 | 7 | 8 | export default class SignUpScreen extends Component { 9 | constructor() { 10 | super(); 11 | this.state = { 12 | user: "", 13 | password: "", 14 | email: "" 15 | }; 16 | } 17 | setItem(key, value) { 18 | this.setState({ [key]: value }); 19 | } 20 | 21 | render() { 22 | return ( 23 | 24 | 29 | 30 | 35 | 36 | 41 | 42 | 46 | 47 | 51 | 52 | ); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Section 3/3.3/App.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { AppContainer } from './Navigation/RootNavigator'; 3 | 4 | export default class App extends Component { 5 | render() { 6 | return ; 7 | } 8 | } -------------------------------------------------------------------------------- /Section 3/3.3/Navigation/RootNavigator.js: -------------------------------------------------------------------------------- 1 | import { StackNav } from './StackNav'; 2 | import { createAppContainer } from "react-navigation"; 3 | 4 | export const AppContainer = createAppContainer(StackNav); 5 | -------------------------------------------------------------------------------- /Section 3/3.3/Navigation/StackNav.js: -------------------------------------------------------------------------------- 1 | import SignUpScreen from "../Screens/SignUpScreen"; 2 | import { TabNav } from './TabNav'; 3 | 4 | 5 | import { createStackNavigator } from "react-navigation"; 6 | 7 | export const StackNav =createStackNavigator( 8 | { 9 | Home: { 10 | screen: TabNav 11 | }, 12 | SignUp: { 13 | screen: SignUpScreen 14 | } 15 | }, 16 | { 17 | initialRouteName: "SignUp", 18 | headerMode: "none" 19 | } 20 | ); -------------------------------------------------------------------------------- /Section 3/3.3/Navigation/TabNav.js: -------------------------------------------------------------------------------- 1 | import HomeScreen from "../Screens/HomeScreen"; 2 | import DetailScreen from "../Screens/DetailScreen"; 3 | 4 | import { createBottomTabNavigator } from "react-navigation"; 5 | 6 | export const TabNav =createBottomTabNavigator( 7 | { 8 | Home: { 9 | screen: HomeScreen 10 | }, 11 | Detail: { 12 | screen: DetailScreen 13 | } 14 | } 15 | ); -------------------------------------------------------------------------------- /Section 4/4.2/HOCBUG.jsx: -------------------------------------------------------------------------------- 1 | const withNewData = Component => props => ; 2 | const withData = Component => props => ; 3 | 4 | withNewData(withData(BaseComponent)) -------------------------------------------------------------------------------- /Section 4/4.2/section4code.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | 3 | class ClassComponent extends Component { 4 | constructor(props) { 5 | super(props); 6 | this.state = { 7 | loading: true 8 | }; 9 | } 10 | 11 | componentDidMount () { 12 | this.setState({ loading: false }); 13 | } 14 | 15 | render() { 16 | return ( 17 | 18 | { (this.state.loading) ? 19 | loading : 20 | text in class component 21 | } 22 | 23 | ); 24 | } 25 | } 26 | 27 | export default ClassComponent; 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | const BaseComponent; 39 | 40 | 41 | -------------------------------------------------------------------------------- /Section 4/4.3/FancyButton.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Text, View } from "react-native"; 3 | import styles from "./Styles/AppStyle"; 4 | 5 | import withNavigationPath from "./WithNav"; 6 | import withStyle from "./WithStyle"; 7 | 8 | const button = props => ( 9 | 10 | {props.text} 11 | 12 | ); 13 | 14 | export const FancyButton = withNavigationPath(withStyle(button)); 15 | -------------------------------------------------------------------------------- /Section 4/4.3/WithNav.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { TouchableOpacity } from "react-native"; 3 | 4 | const withNavigationPath = WrappedComponent => ({ ...props }) => 5 | ( 6 | props.navigation.navigate(props.route) : 10 | () => props.navigation.goBack() 11 | } 12 | > 13 | 14 | 15 | ); 16 | 17 | 18 | 19 | export default withNavigationPath; 20 | -------------------------------------------------------------------------------- /Section 4/4.3/WithStyle.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import styles from "./Styles/AppStyle"; 3 | 4 | const WithStyle = WrappedComponent => { 5 | const HOC = ({ ...props }) => { 6 | return ( 7 | 15 | ); 16 | }; 17 | return HOC; 18 | }; 19 | 20 | export default WithStyle; -------------------------------------------------------------------------------- /Section 5/5.1/renderPropEx.js: -------------------------------------------------------------------------------- 1 | // render props as function 2 | const dataToDisplay = "the data"; 3 | 4 | const ComponentDataProvider = ({ render }) => ( 5 | 6 | { render(dataToDisplay) } 7 | 8 | ) 9 | 10 | const ComponentToProvideRender = () => ( 11 | the data is {data} } /> 12 | ); 13 | 14 | // render props as child 15 | const dataToDisplay = "the data"; 16 | 17 | const ComponentDataProvider = () => ( 18 | 19 | 20 | { dataToDisplay ? dataToDisplay : 'No Data' } 21 | 22 | 23 | ) 24 | 25 | const ComponentToProvideRender = () => ( 26 | 27 | ); 28 | 29 | // would then just be called as 30 | 31 | -------------------------------------------------------------------------------- /Section 5/5.2/FancyButton.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Text } from "react-native"; 3 | import styles from "./Styles/AppStyle"; 4 | 5 | import withNavigationPath from "./WithNav"; 6 | import WithStyle from "./WithStyle"; 7 | 8 | const button = props => ( 9 | {text}} 12 | /> 13 | ); 14 | 15 | export const FancyButton = withNavigationPath(button); 16 | -------------------------------------------------------------------------------- /Section 5/5.2/WithStyle.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { View } from "react-native"; 3 | import styles from "./Styles/AppStyle"; 4 | 5 | const WithStyle = (props) => ( 6 | 14 | { props.render(props.text) } 15 | 16 | ) 17 | 18 | export default WithStyle; -------------------------------------------------------------------------------- /Section 5/5.2/componentComposition.jsx: -------------------------------------------------------------------------------- 1 | 2 | export const FancyButton = props => ( 3 | ( 6 | {text}} 9 | /> 10 | )} 11 | /> 12 | ); 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | // HOC compositon 24 | const button = props => ( 25 | 26 | {props.text} 27 | 28 | ); 29 | 30 | export const FancyButton = withNavigationPath(withStyle(button)); 31 | -------------------------------------------------------------------------------- /Section 5/5.3/FancyInput.js: -------------------------------------------------------------------------------- 1 | import React, { Fragment } from "react"; 2 | import { Text, TextInput } from "react-native"; 3 | import styles from "./Styles/AppStyle"; 4 | 5 | export const FancyInput = props => { 6 | return ( 7 | 8 | {props.item} 9 | props.setItem([props.item], value)} 12 | value={props.value} 13 | /> 14 | { (props.renderValidation) ? props.renderValidation() : null} 15 | 16 | ); 17 | }; 18 | -------------------------------------------------------------------------------- /Section 5/5.3/HomeScreen.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { View } from 'react-native'; 3 | import styles from '../Components/Styles/AppStyle'; 4 | import { FancyButton } from '../Components/FancyButton'; 5 | import { FancyInput } from '../Components/FancyInput'; 6 | import { ValidationMessage } from '../Components/ValidationMessage'; 7 | 8 | export default class HomeScreen extends Component { 9 | constructor() { 10 | super(); 11 | this.state = { 12 | user: '', 13 | password: '' 14 | }; 15 | } 16 | setItem(key, value) { 17 | this.setState({ [key]: value }); 18 | } 19 | 20 | render() { 21 | return ( 22 | 23 | 27 | 28 | ( 35 | 36 | ) 37 | : null 38 | } 39 | /> 40 | 41 | 45 | 46 | 47 | ); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Section 5/5.3/ValidationMessage.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { View, Text } from "react-native"; 3 | 4 | export const ValidationMessage = props => ( 5 | 6 | { props.rule ? 7 | {props.rule} : 8 | No Rule 9 | } 10 | 11 | ); 12 | -------------------------------------------------------------------------------- /Section 6/6.1/SignUpScreen.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from "react"; 2 | import { View, TextInput } from "react-native"; 3 | import styles from "../Components/Styles/AppStyle"; 4 | import { FancyButton } from "../Components/FancyButton"; 5 | import { FancyInput } from "../Components/FancyInput"; 6 | 7 | export default class SignUpScreen extends Component { 8 | constructor() { 9 | super(); 10 | this.state = { 11 | user: "", 12 | password: "", 13 | email: "" 14 | }; 15 | } 16 | setItem(key, value) { 17 | this.setState({ [key]: value }); 18 | } 19 | 20 | render() { 21 | return ( 22 | 23 | { 24 | React.cloneElement(, { 25 | item:"clonedUser", 26 | value:"clonedUser" 27 | }) 28 | } 29 | 34 | 35 | 40 | 41 | 46 | 47 | 51 | 52 | 57 | 58 | ); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /Section 6/6.1/children.jsx: -------------------------------------------------------------------------------- 1 | const arrayOfChildren = React.Children.map(this.props.children, child => InvokeFunction(child)); 2 | 3 | componentDidMount() { 4 | React.Children.forEach(this.props.children, child => { 5 | // if child meets criteria modify 6 | }) 7 | } -------------------------------------------------------------------------------- /Section 6/6.2/SignUpScreen.js: -------------------------------------------------------------------------------- 1 | import React, { Component, Fragment } from "react"; 2 | import { View, Text } from "react-native"; 3 | import styles from "../Components/Styles/AppStyle"; 4 | import { FancyButton } from "../Components/FancyButton"; 5 | import { FancyInput } from "../Components/FancyInput"; 6 | 7 | // fake state to be shared 8 | const showCloneConfig = { 9 | display: true, 10 | item : 'clonedUser', 11 | value: 'showCloneConfigUser' 12 | }; 13 | 14 | const DisplayClone = ({showClone, children}) => (showClone.display) ? React.Children.only(children):null; 15 | 16 | const TheClone = ({item, value}) => ( 17 | 18 | Text in clone 19 | { React.cloneElement(, { item, value }) } 20 | 21 | ); 22 | 23 | export default class SignUpScreen extends Component { 24 | constructor() { 25 | super(); 26 | this.state = { 27 | user: "", 28 | password: "", 29 | email: "" 30 | }; 31 | } 32 | setItem(key, value) { 33 | this.setState({ [key]: value }); 34 | } 35 | 36 | render() { 37 | 38 | return ( 39 | 40 | 41 | 42 | 43 | 44 | 45 | 50 | 51 | 56 | 57 | 62 | 63 | 67 | 68 | 73 | 74 | ); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /Section 6/6.3/CommonForm.js: -------------------------------------------------------------------------------- 1 | import React, { Component, Fragment, cloneElement } from "react"; 2 | 3 | import EmailInput from "./EmailInput"; 4 | import PasswordInput from "./PasswordInput"; 5 | import UserInput from "./UserInput"; 6 | 7 | export default class CommonForm extends Component { 8 | 9 | state = { 10 | isLoggedIn: this.props.isLoggedIn 11 | } 12 | static defaultProps = { 13 | isLoggedIn: false, 14 | children: {} 15 | 16 | } 17 | static EmailInput = EmailInput; 18 | static PasswordInput = PasswordInput; 19 | static UserInput = UserInput; 20 | 21 | componentDidMount() { 22 | const { isLoggedIn } = this.state; 23 | const children = React.Children.map(this.props.children, child => cloneElement(child, { isLoggedIn })); 24 | this.setState({ children }) 25 | } 26 | 27 | render() { 28 | return {this.state.children}; 29 | } 30 | } 31 | 32 | -------------------------------------------------------------------------------- /Section 6/6.3/DetailScreen.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from "react"; 2 | import { View, Text } from "react-native"; 3 | import { FancyButton } from "../Components/FancyButton"; 4 | import { FancyInput } from "../Components/FancyInput"; 5 | import CommonForm from "../Components/CommonForm"; 6 | 7 | import styles from "../Components/Styles/AppStyle"; 8 | 9 | export default class DetailScreen extends Component { 10 | 11 | setItem(key, value) { 12 | this.setState({ [key]: value }); 13 | } 14 | 15 | render() { 16 | return ( 17 | 18 | Welcome to the Details 19 | please enter contact info 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | ); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Section 6/6.3/EmailInput.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { FancyInput } from './FancyInput'; 3 | import { ValidationMessage } from './ValidationMessage'; 4 | 5 | export default class EmailInput extends Component { 6 | constructor() { 7 | super(); 8 | this.state = { 9 | email: '' 10 | }; 11 | } 12 | setItem(key, value) { 13 | this.setState({ [key]: value }); 14 | } 15 | 16 | render() { 17 | const { isLoggedIn } = this.props 18 | return ( 19 | ( 26 | 27 | ) 28 | : null 29 | } 30 | /> 31 | ); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Section 6/6.3/FancyInput.js: -------------------------------------------------------------------------------- 1 | import React, { Fragment } from "react"; 2 | import { Text, TextInput } from "react-native"; 3 | import styles from "./Styles/AppStyle"; 4 | 5 | export const FancyInput = props => { 6 | return ( 7 | 8 | {props.item} 9 | props.setItem([props.item], value)} 12 | value={props.value} 13 | /> 14 | { (props.renderValidation) ? props.renderValidation() : null} 15 | 16 | ); 17 | }; 18 | -------------------------------------------------------------------------------- /Section 6/6.3/HomeScreen.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { View } from 'react-native'; 3 | import styles from '../Components/Styles/AppStyle'; 4 | import { FancyButton } from '../Components/FancyButton'; 5 | import CommonForm from '../Components/CommonForm'; 6 | 7 | export default class HomeScreen extends Component { 8 | 9 | render() { 10 | return ( 11 | 12 | 13 | 14 | 15 | 16 | 17 | 21 | 22 | 23 | ); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Section 6/6.3/PasswordInput.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from "react"; 2 | import { FancyInput } from "./FancyInput"; 3 | import { ValidationMessage } from "./ValidationMessage"; 4 | 5 | export default class PasswordInput extends Component { 6 | constructor() { 7 | super(); 8 | this.state = { 9 | password: '' 10 | }; 11 | } 12 | setItem(key, value) { 13 | this.setState({ [key]: value }); 14 | } 15 | 16 | render() { 17 | const { isLoggedIn } = this.props 18 | return ( 19 | ( 26 | 27 | ) 28 | : null 29 | } 30 | /> 31 | ); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Section 6/6.3/SignUpScreen.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from "react"; 2 | import { View } from "react-native"; 3 | import styles from "../Components/Styles/AppStyle"; 4 | import { FancyButton } from "../Components/FancyButton"; 5 | import CommonForm from '../Components/CommonForm'; 6 | 7 | export default class SignUpScreen extends Component { 8 | 9 | render() { 10 | return ( 11 | 12 | {/* can toggle here to see action */} 13 | 14 | 15 | 16 | 17 | 18 | 19 | 23 | 24 | 29 | 30 | ); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Section 6/6.3/UserInput.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { FancyInput } from './FancyInput'; 3 | import { ValidationMessage } from './ValidationMessage'; 4 | 5 | export default class UserInput extends Component { 6 | constructor() { 7 | super(); 8 | this.state = { 9 | user: '' 10 | }; 11 | } 12 | setItem(key, value) { 13 | this.setState({ [key]: value }); 14 | } 15 | 16 | render() { 17 | const { isLoggedIn } = this.props 18 | return ( 19 | - 1 25 | ? () => ( 26 | 27 | ) 28 | : null 29 | } 30 | /> 31 | ); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Section 7/7.2/Contexts/EntryContext.js: -------------------------------------------------------------------------------- 1 | import React, { Component, createContext } from 'react'; 2 | 3 | export const EntryContext = createContext(); 4 | 5 | export class EntryProvider extends Component { 6 | constructor(props) { 7 | super(props); 8 | this.toggleMessage = () => { 9 | this.setState(state => ({ 10 | entryText: 11 | (state.entryText === 'if you have an account please sign in') 12 | ? 'Thank you for visiting!' 13 | : 'if you have an account please sign in' 14 | })); 15 | }; 16 | this.state = { 17 | toggleMessage: this.toggleMessage, 18 | entryText: 'if you have an account please sign in' 19 | }; 20 | } 21 | 22 | render() { 23 | return ( 24 | 25 | {this.props.children} 26 | 27 | ); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Section 7/7.2/CustomText.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Text, Platform } from "react-native"; 3 | 4 | export const CustomText = ({ entryText }) => ( 5 | 13 | {entryText} 14 | 15 | ); 16 | -------------------------------------------------------------------------------- /Section 7/7.2/CustomView.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { View, TouchableOpacity } from "react-native"; 3 | 4 | import { CustomText } from './CustomText'; 5 | import { EntryContext } from "../Contexts/EntryContext"; 6 | 7 | // prop drilling example 8 | // export const CustomView = props => ( 9 | // 10 | // 11 | // 12 | // ); 13 | 14 | export const CustomView = () => ( 15 | 16 | 17 | {({ entryText, toggleMessage }) => ( 18 | 19 | 20 | 21 | )} 22 | 23 | 24 | ); 25 | 26 | -------------------------------------------------------------------------------- /Section 7/7.2/SignUpScreen.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from "react"; 2 | import { View } from "react-native"; 3 | import styles from "../Components/Styles/AppStyle"; 4 | 5 | import { EntryProvider } from '../Contexts/EntryContext'; 6 | 7 | import { FancyButton } from "../Components/FancyButton"; 8 | import { CustomView } from "../Components/CustomView"; 9 | 10 | import CommonForm from "../Components/CommonForm"; 11 | 12 | 13 | export default class SignUpScreen extends Component { 14 | render() { 15 | return ( 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 35 | 36 | ); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Section 7/7.2/componentComp.js: -------------------------------------------------------------------------------- 1 | 2 | // custom view 3 | 4 | {props.children} 5 | 6 | 7 | 8 | // signup implementation 9 | 10 | 11 | -------------------------------------------------------------------------------- /Section 7/7.3/CommonForm.js: -------------------------------------------------------------------------------- 1 | import React, { Component, Fragment, cloneElement } from "react"; 2 | 3 | import EmailInput from "./EmailInput"; 4 | import PasswordInput from "./PasswordInput"; 5 | import UserInput from "./UserInput"; 6 | 7 | export default class CommonForm extends Component { 8 | 9 | static EmailInput = EmailInput; 10 | static PasswordInput = PasswordInput; 11 | static UserInput = UserInput; 12 | 13 | render() { 14 | return {this.props.children}; 15 | } 16 | } 17 | 18 | -------------------------------------------------------------------------------- /Section 7/7.3/SignUpScreen.js: -------------------------------------------------------------------------------- 1 | import React, { Component, Fragment } from "react"; 2 | import { View, TouchableOpacity, Text } from "react-native"; 3 | import styles from "../Components/Styles/AppStyle"; 4 | 5 | import { EntryProvider } from '../Contexts/EntryContext'; 6 | import { UserProvider, UserContext } from "../Contexts/UserContext"; 7 | 8 | import { FancyButton } from "../Components/FancyButton"; 9 | import { CustomView } from "../Components/CustomView"; 10 | import CommonForm from "../Components/CommonForm"; 11 | import { CustomText } from "../Components/CustomText"; 12 | 13 | export default class SignUpScreen extends Component { 14 | render() { 15 | return ( 16 | 17 | {/* do this and then demo come back and do logout button*/} 18 | 19 | 20 | 21 | {({ isLoggedIn }) => ( 22 | 23 | 24 | 25 | 26 | 27 | )} 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 43 | 44 | 45 | {({ logout }) => ( 46 | 47 | 50 | 51 | 52 | 53 | )} 54 | 55 | 56 | 57 | ); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /Section 7/7.3/UserContext.js: -------------------------------------------------------------------------------- 1 | import React, { Component, createContext } from 'react'; 2 | 3 | export const UserContext = createContext(); 4 | 5 | export class UserProvider extends Component { 6 | constructor(props) { 7 | super(props); 8 | this.state = { 9 | isLoggedIn: true 10 | }; 11 | } 12 | 13 | render() { 14 | return ( 15 | this.setState({ isLoggedIn: false }) 18 | }}> 19 | {this.props.children} 20 | 21 | ); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Section 8/8.1/complexComponent.js: -------------------------------------------------------------------------------- 1 | export default class Comp extends Component { 2 | state = { 3 | intialValue: true 4 | } 5 | 6 | componentDidMount() { 7 | // set initital value based on fetch 8 | } 9 | 10 | componentWillMount() { 11 | // set initital value based on state 12 | } 13 | 14 | componentWillUnmount() { 15 | // set initital value back to true 16 | } 17 | 18 | componentDidUpdate = (prevProps, prevState) => { 19 | // set initital value based on prevProps, prevState 20 | }; 21 | 22 | componentWillReceiveProps(nextProps) { 23 | // set initital value based on nextProps 24 | } 25 | 26 | render() { 27 | return ( 28 | 29 | {this.state.intialValue} 30 | 31 | ) 32 | } 33 | } -------------------------------------------------------------------------------- /Section 8/8.1/customHook.js: -------------------------------------------------------------------------------- 1 | const useCustomHook = () => { 2 | const [state, setState] = useState(initialState); 3 | 4 | useEffect(() => { 5 | const subscription = props.source.subscribe(state); 6 | return () => { 7 | subscription.unsubscribe(state); 8 | }; 9 | }); 10 | 11 | return state; 12 | } 13 | -------------------------------------------------------------------------------- /Section 8/8.2/HookScreen.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from "react"; 2 | import { View, Text, Alert, TouchableOpacity } from "react-native"; 3 | 4 | import styles from "../Components/Styles/AppStyle"; 5 | 6 | export const HookScreen = props => { 7 | 8 | const [seconds, setSeconds] = useState(0); 9 | const [inScreen, leftScreen] = useState(false); 10 | 11 | useEffect(() => { 12 | let timer = setInterval (()=>setSeconds(seconds+1), 1000); 13 | return () => clearInterval(timer) 14 | }); 15 | 16 | useEffect(() => { 17 | return () => (seconds > 0) ? 18 | (Alert.alert("Time on Screen", `you spent ${seconds} seconds on the hook screen`, [{ text: "OK" }])) : null 19 | },[inScreen]); 20 | 21 | return ( 22 | 23 | { seconds } 24 | { 27 | leftScreen(true) 28 | props.navigation.goBack() 29 | } 30 | } 31 | > 32 | go back 33 | 34 | 35 | ); 36 | }; 37 | -------------------------------------------------------------------------------- /Section 8/8.2/SignUpScreen.js: -------------------------------------------------------------------------------- 1 | import React, { Component, Fragment } from "react"; 2 | import { View, TouchableOpacity, Text } from "react-native"; 3 | import styles from "../Components/Styles/AppStyle"; 4 | 5 | import { EntryProvider } from '../Contexts/EntryContext'; 6 | import { UserProvider, UserContext } from "../Contexts/UserContext"; 7 | 8 | import { FancyButton } from "../Components/FancyButton"; 9 | import { CustomView } from "../Components/CustomView"; 10 | import CommonForm from "../Components/CommonForm"; 11 | import { CustomText } from "../Components/CustomText"; 12 | 13 | export default class SignUpScreen extends Component { 14 | render() { 15 | return ( 16 | 17 | {/* do this and then demo come back and do logout button*/} 18 | 19 | 20 | 21 | {({ isLoggedIn }) => ( 22 | 23 | 24 | 25 | 26 | 27 | )} 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 43 | 44 | 45 | {({ logout }) => ( 46 | 47 | 50 | 51 | 52 | 53 | )} 54 | 55 | 56 | 57 | ); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /Section 8/8.2/StackNav.js: -------------------------------------------------------------------------------- 1 | import SignUpScreen from "../Screens/SignUpScreen"; 2 | import { HookScreen } from '../Screens/HookScreen'; 3 | import { TabNav } from './TabNav'; 4 | 5 | 6 | import { createStackNavigator } from "react-navigation"; 7 | 8 | export const StackNav =createStackNavigator( 9 | { 10 | Home: { 11 | screen: TabNav 12 | }, 13 | SignUp: { 14 | screen: SignUpScreen 15 | }, 16 | Hook: { 17 | screen: HookScreen 18 | } 19 | }, 20 | { 21 | initialRouteName: "SignUp", 22 | headerMode: "none" 23 | } 24 | ); -------------------------------------------------------------------------------- /Section 8/8.2/sideEffect.js: -------------------------------------------------------------------------------- 1 | class ClassSideEffect extends Component { 2 | componentDidMount() { 3 | // subscripe to api 4 | // add listener for something 5 | } 6 | componentWillUnmount() { 7 | // unsubscribe to api 8 | // remove listener for something 9 | } 10 | } 11 | const FunctionalSideEffect = () => { 12 | useEffect(() => { 13 | // subscripe to api 14 | // unsubscribe from api 15 | }); 16 | useEffect(() => { 17 | // add listener for something 18 | // remove listener for something 19 | }); 20 | } -------------------------------------------------------------------------------- /Section 8/8.2/useContext.js: -------------------------------------------------------------------------------- 1 | const ColorContext = React.createContext("blue"); 2 | 3 | const ColorProvider = props => { 4 | 5 | const [color, toggleColor] = useState("blue"); 6 | return ( 7 | 8 | 10 | toggleColor(prevColor => (prevColor === "blue" ? "green" : "blue"))} 11 | > 12 | Change Color 13 | 14 | {props.children} 15 | 16 | ); 17 | }; 18 | 19 | const BackGroundComponent = props => { 20 | let value = useContext(ColorContext); 21 | return ( 22 | 23 | {props.children} 24 | 25 | ); 26 | } 27 | const ImplementContextComponent = () => { 28 | const [count, setCount] = useState(0); 29 | let backgroundColor = useContext(ColorContext); 30 | return ( 31 | 32 | 33 | You pressed {count} times 34 | setCount(count + 1)}> 35 | press me 36 | 37 | 38 | 39 | ); 40 | }; -------------------------------------------------------------------------------- /Section 8/8.2/useEffect.js: -------------------------------------------------------------------------------- 1 | import React, { useEffect } from "react"; 2 | import { View, Text, Alert } from "react-navite"; 3 | 4 | const UseEffectComponent = () => { 5 | useEffect(() => { 6 | Alert.alert("use effect title", "component has mounted", [{ text: "OK" }]); 7 | 8 | return () => 9 | Alert.alert("use effect title", "component has unmounted", [ 10 | { text: "OK" } 11 | ]); 12 | }); 13 | 14 | return ( 15 | 16 | useEffect is neat 17 | 18 | ); 19 | }; 20 | -------------------------------------------------------------------------------- /Section 8/8.2/useState.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import { View, TouchableOpacity, Text } from 'react-navite'; 3 | 4 | class ClassComponent extends React.Component { 5 | constructor(props) { 6 | super(props); 7 | this.state = { 8 | count: 0 9 | }; 10 | } 11 | render() { 12 | return ( 13 | 14 | You pressed {count} times 15 | this.setState({ count: this.state.count + 1 })}> 16 | press here 17 | 18 | 19 | ); 20 | } 21 | } 22 | 23 | const UseStateComponent = () => { 24 | const [count, setCount] = useState(0); 25 | return ( 26 | 27 | You pressed {count} times 28 | setCount(count + 1)}> 29 | press here 30 | 31 | 32 | ); 33 | } 34 | 35 | -------------------------------------------------------------------------------- /Section 8/8.3/EmailInput.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react"; 2 | import { FancyInput } from "./FancyInput"; 3 | import { ValidationMessage } from "./ValidationMessage"; 4 | 5 | export default (EmailInput = props => { 6 | const [email, setEmail] = useState(""); 7 | 8 | const { isLoggedIn } = props; 9 | return ( 10 | 17 | : null 18 | } 19 | /> 20 | ); 21 | }); 22 | -------------------------------------------------------------------------------- /Section 8/8.3/FancyInput.js: -------------------------------------------------------------------------------- 1 | import React, { Fragment } from "react"; 2 | import { Text, TextInput } from "react-native"; 3 | import styles from "./Styles/AppStyle"; 4 | 5 | export const FancyInput = props => { 6 | return ( 7 | 8 | {props.item} 9 | props.setItem(value)} 12 | value={props.value} 13 | /> 14 | { (props.renderValidation) ? props.renderValidation() : null} 15 | 16 | ); 17 | }; 18 | -------------------------------------------------------------------------------- /Section 8/8.3/HomeScreen.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { View, Text } from "react-native"; 3 | import styles from "../Components/Styles/AppStyle"; 4 | import { FancyButton } from "../Components/FancyButton"; 5 | import CommonForm from "../Components/CommonForm"; 6 | import { useScreenTimer } from "../Hooks/UseScreenTimer"; 7 | 8 | export default (HomeScreen = props => { 9 | const screenTimer = useScreenTimer(); 10 | let { seconds } = screenTimer; 11 | 12 | return ( 13 | 14 | { seconds } 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | ); 23 | }); 24 | -------------------------------------------------------------------------------- /Section 8/8.3/HookScreen.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from "react"; 2 | import { View, Text, TouchableOpacity, Alert } from "react-native"; 3 | 4 | import styles from "../Components/Styles/AppStyle"; 5 | import { useScreenTimer } from "../Hooks/UseScreenTimer"; 6 | 7 | export const HookScreen = props => { 8 | const screenTimer = useScreenTimer(); 9 | let { seconds } = screenTimer; 10 | const [inScreen, leftScreen] = useState(false); 11 | 12 | useEffect(() => { 13 | return () => 14 | seconds > 0 15 | ? Alert.alert( 16 | "Time on Screen", 17 | `you spent ${seconds} seconds on the last screen`, 18 | [{ text: "OK" }] 19 | ) 20 | : null; 21 | }, [inScreen]); 22 | return ( 23 | 24 | { seconds } 25 | { 28 | leftScreen(true) 29 | props.navigation.goBack() 30 | } 31 | } 32 | > 33 | go back 34 | 35 | 36 | ); 37 | }; 38 | -------------------------------------------------------------------------------- /Section 8/8.3/PasswordInput.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react"; 2 | import { FancyInput } from "./FancyInput"; 3 | import { ValidationMessage } from "./ValidationMessage"; 4 | 5 | export default (PasswordInput = props => { 6 | const [password, setPassword] = useState(""); 7 | const { isLoggedIn } = props; 8 | return ( 9 | ( 16 | 17 | ) 18 | : null 19 | } 20 | /> 21 | ); 22 | }); 23 | -------------------------------------------------------------------------------- /Section 8/8.3/UseScreenTimer.js: -------------------------------------------------------------------------------- 1 | import { useState, useEffect } from "react"; 2 | 3 | export const useScreenTimer = () => { 4 | const [seconds, setSeconds] = useState(0); 5 | 6 | useEffect(() => { 7 | let timer = setInterval(() => setSeconds(seconds + 1), 1000); 8 | return () => clearInterval(timer); 9 | }); 10 | 11 | return { 12 | seconds, 13 | setSeconds 14 | }; 15 | }; 16 | -------------------------------------------------------------------------------- /Section 8/8.3/UserInput.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react"; 2 | import { FancyInput } from "./FancyInput"; 3 | import { ValidationMessage } from "./ValidationMessage"; 4 | 5 | export default (UserInput = props => { 6 | const [user, setUser] = useState(""); 7 | const { isLoggedIn } = props; 8 | return ( 9 | -1 15 | ? () => 16 | : null 17 | } 18 | /> 19 | ); 20 | }); 21 | --------------------------------------------------------------------------------