├── 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 |
12 | - Understand the benefit of separating data components in the Container Component pattern
13 |
- Understand the purpose of Higher Order Components (HOCs), and share code even when significant changes happen between each platform
14 |
- Develop a deep understanding of the Render Props pattern and how it can better serve your React Native application code sharing abilities as opposed to using an HOC
15 |
- Clean up your codebase, and focus on higher-level problems for presentation by using the Compound Component pattern
16 |
- Gain insights into the Context API, and solve the painful problem of prop drilling through multiple components
17 |
- Take your code sharing to the next level with hooks in React Native
18 |
- Work with the Flexbox pattern, which React Native utilizes to enhance your app's presentation
19 |
- Utilize multiple navigation options to handle multiple screens in your application
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 |
--------------------------------------------------------------------------------