Website Links

Monday, 8 May 2017

React Native #9 - Babel

Babel is a dependency that React Native has. Babel lets you write ES2016/ES6 and then it converts this to JavaScript (ES5) that will run on your browser. This is because at the current point in time, the latest version of all major browsers have interpreters that can interpret ES5.

ES2015 adds syntactic sugar to ES5, that can result in faster JavaScript development. It can also result in tidier more readable source code, although of course readability is heavily opinion based so ES6 syntax may not be for everyone. It aims to tackle some of JavaScript's shortcomings addressed by TypeScript/CoffeeScript. This means you can write lambda expressions, JSX, and other syntax available in ES2015.

To write ES2015 in React Native apps you don't need to do any additional work as it is configured by default. However, you can write straight JavaScript if you want to.

References

Try Babel
JSX
JavaScript and ECMAScript

Tuesday, 4 April 2017

CORS & Preflight Requests

When you make a cross domain request from your website you may have your request fail. One of the potential causes for this is that the API you're calling does not handle preflight requests. You will know that this is the case because you will see an OPTIONS request to the API you made the call to, but this call will fail and no subsequent GET/POST/PUT or whatever other HTTP call you were trying to make will be made.

What's the point?

Preflight requests arose as CORS made it possible to specify more headers and requests methods in a request than was previously possible to make cross origin. This meant that some servers were developed under the assumption that they would not receive these cross-origin requests and would thus be protected from them. A preflight request provides a way for the server to opt into receiving these requests, as the server must respond to the OPTIONS request with the types of methods, headers, and origins that it accepts. This protects the server (particularly older servers), without the need for the server to change as if it doesn't respond to the OPTIONS request with headers that match the request, then the subsequent request will not be made.

Note: not all HTTP requests will have a preflight request. If the request was possible cross-origin prior to CORS, then a preflight request will not be made as older servers should have handled any security around these requests themselves.

How to get the preflight request to succeed?

Assuming that the server responds to the OPTIONS request successfully, the website should not need to make any further changes as the further requests will be handled by the browser. So if you are using a publicly exposed API and your request is failing on the OPTIONS request, you will need to confirm that the API is accepting your domain, headers and method you submitted the request with. You can do this by checking the OPTIONS response meets the following criteria:
  • Access-Control-Allow-Headers header with comma-separated list of headers you made your request with
  • Access-Control-Allow-Origin header with * or domain matching that which you are making the request from
  • Access-Control-Allow-Methods header with comma-separated list of methods you can access the endpoint with
  • Status is 200

If you want to enable your API to handle preflight requests, then you will need to be able to accept and OPTIONS request and respond to the requester with the above headers/status. The actually implementation of this will be down to the technologies you have developed your APIs using but there will commonly be APIs available to enable CORS. Note: your API that is available due cross-domain will also need to have GET/PUT/POST etc, with these headers.

References

CORS Access Control

Monday, 3 April 2017

React Native #8 - State

Previously, we discussed how we can make reusable components by passing data to a component using props. State can also be used to help us provide data to a component. However, the difference is that state is used to hold values that change, and when it changes it will trigger updates to the components that reference it. State should generally be initialised in the constructor, and set state should be used to update it.

As a simple example, consider a UI that has a text input for the users name and then a text component that greets them, it would appear as follows:

  // Import necessary components
  import React, { Component } from 'react';
  import { Text, View, TextInput, StyleSheet } from 'react-native';
  import { Constants } from 'expo';
  
  export default class App extends Component {
 
    // Initialise state to avoid state being undefined
    // state is just a javascript object with properties
    // want to keep track of the state of
    constructor(props) {
      super(props);
      this.state = { text: '' };
    }
    
    render() {
      return (
        <View style={styles.container}>
          // Render text input and when text changes
          // update state
          <TextInput
            placeholder='Name'
            style={styles.textInput}
            onChangeText={(text) => this.setState({text})}
            value={this.state.text}
          />
        
          // Render text when text changes for input
          // the hello message should update to match
          // the new state
          <Text style={styles.paragraph}>
            Hello {this.state.text}
          </Text>
        </View>
      );
    }
  }

  const styles = StyleSheet.create({
    container: {
      flex: 1,
      alignItems: 'center',
      justifyContent: 'center',
      paddingTop: Constants.statusBarHeight,
      backgroundColor: '#ecf0f1',
    },
    paragraph: {
      margin: 24,
      fontSize: 18,
      fontWeight: 'bold',
      textAlign: 'center',
      color: '#34495e',
    },
    textInput: {
      height: 40,
      borderColor: 'gray', 
      borderWidth: 1
    }
  });

Friday, 27 January 2017

React Native #7 - React vs React Native

When developing using React Native, we reference two separate libraries (both React and React Native).

React

React is more generic and also used on the web, essentially it ensures all the components work together. It is also responsible for understanding how components should behave. Any components you define will extend Component which is defined by React.

React Native

Provides the default core components that translate to native components. It can take a component and place it on the mobile phone's screen. It is basically the link between your Javascript and the mobile device.

Thursday, 26 January 2017

ESLint

ESLint is a tool that analyses your JavaScript for potential errors and can be installed into many common text editors. This can help you pick up errors in your JavaScript without reloading your website or react native app, which can help you increase your productivity... YAY!

ESLint has a few setup layers - this is split into editor specific config and project specific config. This means we can configure which ESLint rules to validate our code using on a project by project basis. There are some preset configurations for this so that as a developer you don't need to add rules one by one.

Setting up ESLint in Sublime

  • Install eslint globally using npm:
    npm install -g eslint
  • Install Package Control
  • Do per project setup:
    • Install a set of rules that you want eslint to use to validate your code (there are other ones out there but here's an example)!
      npm install --save-dev eslint-config-rallycoding
    • Create a file in your project's root directory called .eslintrc
    • Tell eslint which rules to use by adding the following to the file:
        {
          "extends": "rallycoding"
        }
      
      Noting that it is important that these are double quoted.
  • Use Package Control to install linter and eslint to Sublime Text
    • Open up the command palette (Tools > Command Palette or command + shift + P)
    • Search for install and click on install package
    • Once this has loaded, search and click on SublimeLinter
    • Repeat for the package SublimeLinter-contrib-eslint
  • Exit out of Sublime Text, and reopen
  • Delete a semi-colon and save to confirm eslint is setup correctly. If this doesn't show errors, then move your cursor around a bit.

Tuesday, 24 January 2017

React Native #6 - Navigator

In React Native, to add navigation to your app you can use the Navigator component. You can have as many navigators as you want in your app e.g. you may have one for your whole app or multiple if you are using tabs with different navigation stacks for each tab. This tutorial will explain how to add a single navigator to your react native app. Firstly, add the navigator as the base for your application so specify it in the index.ios.js and the index.android.js:

  // Import the Navigator from React Native 
  import React, { Component } from 'react';
  import {
    AppRegistry,
    Navigator
  } from 'react-native';

  import MainScene from './app/scenes/mainScene'
  import AddGoalScene from './app/scenes/addGoalScene'

  export default class Goalie extends Component {
    renderScene(route, navigator) {
      // Specify the properties to pass to the scene you will 
      // render. It is useful to pass the navigator around the
      // scenes so that you can push and pop to the navigation
      // stack. 
      var globalNavigatorProps = {
        navigator: navigator,
        goal: route.goal
      };

      // Based on the route passed to the navigator you can
      // determine which scene to render.
      switch(route.ident) {
        case "MainScene":
          return ( <MainScene {...globalNavigatorProps} />);
        case "AddGoalScene":
          return ( <AddGoalScene {...globalNavigatorProps} />);
        default:
          return ( <MainScene {...globalNavigatorProps}  />);
      }

    }

    render() {
      return (
        // Render your navigator
        // You must specify an initial route, which will become
        // your root view for the app. The initialRoute is just 
        // an object with an identifier you can use to define 
        // which screen should be displayed, and whatever other
        // info you would like to pass in.
        // You must also specify a renderScene function which
        // has the args route and navigator, this must return
        // what you would like to render on the navigation stack.
        <Navigator 
          initialRoute={{ident: "MainScene", goal: "MainScene" }} 
          renderScene={this.renderScene} />
      );
    }
  }

  AppRegistry.registerComponent('Goalie', () => Goalie);


The next step is to be able to add and remove from the navigation stack. For simplicity, I will demonstrate this using back and forward buttons:

  import React, { Component } from 'react';
  import {
    Button
  } from 'react-native';

  import ViewContainer from 
    '../components/viewContainer/ViewContainer'

  export default class MainScene extends Component {

    // Passes new route to the navigator, the scene
    // with the corresponding identifier will get rendered.
    navigateToAddGoal() {
      this.props.navigator.push({
        ident: "AddGoalScene",
        goal: this.props.goal
      });
    }

    // Removes the current scene from the navigator's
    // stack, and goes back to the previous scene. 
    goBack() {
      this.props.navigator.pop();
    }

    render() {
      return (
        <ViewContainer>
          <Button title= "Back" 
            onPress = { (event) => this.goBack() }/>
          <Button title= "Forward" 
            onPress = { (event) => this.navigateToAddGoal() }/>
        </ViewContainer>
      );
    }
  }

C# - Lambda Expressions

Lambda expressions are anonymous methods that have:
  • No access modifier
  • No name
  • No return statement

We use them for convenience so that we can write less code to achieve the same result. We also use them to make our code more readable. You can define a lambda expression as follows:

    // The generic types defined within the < and > represent the input
    // and output values, the first x types being the inputs
    // and the last type being the output 
    Func increment = number => number++;

    // You can call a lambda expression like this: 
    int incrementedNumber = increment(1);

    // A lambda expression with no arguments is defined like this: 
    Func greeting = () => "Hello world!";

    // A lambda expression with multiple arguments is defined like this: 
    Func add = (x, y) => x + y;

    // A lambda expression can also access variables in scope: 
    var name = "Chelsea";
    Func greetPerson = () => "Hello " + name;

    // This would print out "Hello Chelsea":   
    Console.WriteLine(greetPerson());

    // This would print out "Hello Tessa":   
    name = "Tessa";
    Console.WriteLine(greetPerson());



References

C# Lambda Expressions on YouTube https://youtu.be/SLPJ2GqF2Ts?t=5m14s