There is always something you feel you can't go live without… You develop that feature, and then you think "Well this would be really beneficial to my product too"… So how do you know when to go live? Well I am going to share with you a scenario I encountered recently when trying to determine a launch date for our product and what the MVP would look like.
Firstly, I'll describe our product fairly briefly… It is a product that connects job seekers with potential employers. When thinking about how to market our product we had to start thinking about what would attract job seekers and what would attract employers. We decided it was rather cyclical, which employers would bother to come to use our product if we didn't have an existing user base of talent? Similarly, if there are no employers to connect with why would any talent use our application?
However, we also had a tool within the product that job seekers would use… This tool was not intended to be used independently of the rest of the product. However, with some tweaks it could become a standalone application that we could use to attract talent and form a user base which we could then roll out further features and updates to.
So we refocused… We channeled our energy into perfecting that small portion of our app. That way we could start marketing and growing a user base whilst we still developed the main product in the background. We went from a feature that was barely part of our MVP to a feature that was our MVP. We did this all by thinking about how we could grow our user base and which users would be easier to attract.
When you are defining your MVP think about what it will take to get people using your product. You can then roll out additional features down the line, but you already have the recognition so it gets a bit easier. Your marketing team can start working their magic sooner, and you will learn a bit more about what the users want and what they don't want. This means it can be easier to pivot early, which can save a lot of valuable development time.
Thursday, 4 July 2019
Tuesday, 23 April 2019
React - Testing with Jest
This post is just a basic of how to setup for Jest testing with React. There will be more posts in the future to cover different assertion types, how to integrate Jest tests into your CI pipeline and how to use Enzyme for rendering components. By default Jest is included in React, and it will pick up tests in either the __tests__ directory or with a filename ending in .test.js. There are different advantages to each of these. I personally feel like __tests__ is better for larger projects, but this may be down to my C# background where you'll commonly have a separate project for tests. As I tend to be of the opinion that you can always grow a program overtime I tend to favour this in all cases. However, the advantage of appending .test.js to the end of your filename is that your file can reside in the same directory as the source code you're testing, which means that import statements tend to be a bit less complicated. Whatever your decision, it's supported and Jest will pick up your test cases.
By default, your React app likely has an App.test.js file which I moved and renamed to __tests__/App.js. Now I was pretty bad and didn't write any test cases for a while, and went on developing without running this test... So, when I finally ran Jest tests using the command
But my test was still failing! The error was:
By default, your React app likely has an App.test.js file which I moved and renamed to __tests__/App.js. Now I was pretty bad and didn't write any test cases for a while, and went on developing without running this test... So, when I finally ran Jest tests using the command
npm testI found my test was failing! The first cause of failure was that when I rendered my App on index.js I had actually surrounded it in a <BrowserRouter> tag, which meant that when <App> was rendered on its own, it was missing the <BrowserRouter> surrounding the <Switch> and <Route>s. So this test actually allowed me to refactor my code into a more readable and sensible structure... And that was just the basic included test!
But my test was still failing! The error was:
TypeError: window.matchMedia is not a functionThe cause of this is that Jest uses JSDom to create a browser environment, which doesn't support window.matchMedia, and I was using this in my code. After some googling, it turns out that it could be mocked out. So I created a __mocks__/matchMedia.js file with the following contents:
window.matchMedia = jest.fn().mockImplementation(query => {
return {
matches: false,
media: query,
onchange: null,
addListener: jest.fn(),
removeListener: jest.fn(),
};
});
In my __tests__/App.js file I imported this mock and low and behold a different error! This error was about having a store, I used the "redux-mock-store" npm package to mock out my redux store and wrapping my <App> in a <Provider>, and my __tests__/App.js file ended up looking like this:
import React from 'react';
import ReactDOM from 'react-dom';
import '../__mocks__/matchMedia';
import { Provider } from 'react-redux';
import configureMockStore from 'redux-mock-store';
import App from '../App';
const mockStore = configureMockStore();
const store = mockStore({});
describe('App', () => {
it('renders without crashing', () => {
const div = document.createElement('div');
ReactDOM.render((
<Provider store={store}>
<App />
</Provider>
), div);
});
});
And guess what... It PASSED!
Friday, 12 April 2019
React/React Native - Higher Order Components
Higher order components is probably one of my favourite patterns that I have come across for React/React Native. It is when you pass a component to a function and it returns the component with additional functionality. This is very useful for code reuse. You may have seen this used before with the connect function provided by redux.
I typically use this for auto login if a user were to navigate to a login/register page e.g.
import React, { Component } from 'react'
import { connect } from 'react-redux'
import { setCurrentUser } from '../actions/index'
import { bindActionCreators } from 'redux'
export const withAutoLogin = (Scene) => {
// New component that wraps our existing component and adds
// additional functionality
class WithAutoLogin extends Component {
constructor(props) {
super(props);
// If there is a current user, navigate to home page
if (this.props.currentUser) {
...
}
}
render() {
return (
// apply props to component
<Scene {...this.props} />
);
}
}
// Connecting to redux
function mapStateToProps(state) {
return {
currentUser: state.currentUser
}
}
function mapDispatchToProps(dispatch) {
return bindActionCreators({
setCurrentUser: setCurrentUser
}, dispatch);
}
return connect(mapStateToProps,
mapDispatchToProps)(WithAutoLogin);
}
Google Cloud Build - Automating Function Deployment
The following is how to setup a basic google cloud function deployment using google cloud build.
If you have any permission issues you might need to go to Project Settings > IAM and make sure a member exists with the following roles:
- Go to Google Cloud Build (https://console.cloud.google.com/cloud-build/triggers)
- Add trigger
- Select your source
- Authenticate with your source
- Adjust your trigger settings
- Under Build Configuration, select cloudbuild.yaml
- Add substitution variable "_NAME" and provide the name of the function you want to deploy
- Add a cloudbuild.yaml to your repository e.g.
steps: - name: 'gcr.io/cloud-builders/gcloud' args: ['beta', 'functions', 'deploy', '${_NAME}', '--trigger-http']
If you have any permission issues you might need to go to Project Settings > IAM and make sure a member exists with the following roles:
- Cloud Build Service Account
- Cloud Build Editor
- Cloud Functions Developer
Monday, 12 November 2018
Sharing JS Code Across BitBucket Repositories
Recently, I have been writing APIs in node.js with the express framework, a React website and a React Native app that have some shared code. These are spread across several repositories, so I needed a way to share code across the repositories. So I created a node package in another repository.
Then I needed to figure out how to access the repository and install my package via npm. Fortunately, this proved to be relatively easy… Go to your account's BitBucket Settings > App Passwords. From here, you can create an app password and grant read access to your repositories. Then all you need to do is go to your package.json and add to your dependencies e.g.
If you then execute the "npm install" command this should install the repo to your node_modules folder.
But what happens when you push changes to the common repository? How do I run the code with the latest commits? Simply add an additional line to your package.json scripts:
Then when you want to run with the latest changes use
Then I needed to figure out how to access the repository and install my package via npm. Fortunately, this proved to be relatively easy… Go to your account's BitBucket Settings > App Passwords. From here, you can create an app password and grant read access to your repositories. Then all you need to do is go to your package.json and add to your dependencies e.g.
{
…
dependencies: {
…,
"[PACKAGE_NAME]": "git+https://[BITBUCKET_USERNAME]:
[APP_PASSWORD]@bitbucket.org/PROJECT_NAME/
REPOSITORY_NAME.git#BRANCH_NAME"
},
…
}
If you then execute the "npm install" command this should install the repo to your node_modules folder.
But what happens when you push changes to the common repository? How do I run the code with the latest commits? Simply add an additional line to your package.json scripts:
{
…
scripts: {
…,
"clean-start": "rm -rf -- node_modules/[PACKAGE_NAME];
npm install; npm start;"
},
…
}
Then when you want to run with the latest changes use
npm run clean-startinstead of
npm start
Friday, 2 November 2018
How to create a VERY basic (and useless) Node Package
This is just the absolute basics of a node package so that you can install it via npm, whether it be a private or publicly accessible repo. See my follow up post about how to install a package that's in a private bitbucket repo.
Firstly, setup a basic package.json as follows:
The name is one of the key properties in the package.json as it will represent your node package name. Any repo with a package.json can be published to npm. It is also recommended that your repo contains a readme.md in the root of the repo, this will be the documentation displayed on the npm website, if you choose to publish it there.
Next you will need some content exported in your index.js that other code can import and use. For the purposes of this example, I've kept it quite simple:
Then you can import it and use it in your code. If you're struggling with more complicated node packages, then I recommend taking a look at one of the many existing and much more practical open source node packages that already exist on npm.
Firstly, setup a basic package.json as follows:
{
"name": "tripwiretech-common",
"version": "1.0.0",
"description": "Tripwiretech common code",
"main": "index.js",
"author": "Tripwiretech",
"license": "ISC",
"scripts": {
"start": "node index.js"
}
}
The name is one of the key properties in the package.json as it will represent your node package name. Any repo with a package.json can be published to npm. It is also recommended that your repo contains a readme.md in the root of the repo, this will be the documentation displayed on the npm website, if you choose to publish it there.
Next you will need some content exported in your index.js that other code can import and use. For the purposes of this example, I've kept it quite simple:
module.exports = {
Countries: ["Australia", "New Zealand", "South Africa"],
Sports: ["Rugby", "Cricket"]
}
Then you can import it and use it in your code. If you're struggling with more complicated node packages, then I recommend taking a look at one of the many existing and much more practical open source node packages that already exist on npm.
Monday, 26 March 2018
Swift 4 - Adding Admob Interstitial Ads to your iOS App
- Sign up for or sign in to Admob
- Add an App in Admob
- Add an Ad unit in Admob - Choose Interstitial. You can set ad type, frequency capping and eCPM floor under advanced settings
- You should now have an Ad Unit ID and App Id which will be used in displaying interstitial ads to the user
- In your code, create a file InterstitialAd.swift, it should have the following code:
let adController = InterstitialAd() import GoogleMobileAds class InterstitialAd : NSObject, GADInterstitialDelegate { var testAdId = "ca-app-pub-3940256099942544/4411468910" var adId = "[YOUR AD UNIT ID GOES HERE]" var interstitial : GADInterstitial! func createAndLoadInterstitial() { interstitial = GADInterstitial(adUnitID: testAdId) interstitial.delegate = self interstitial.load(GADRequest()) } // Load new interstitial on close so that adController // is ready for the next time showAd is called func interstitialDidDismissScreen(_ ad: GADInterstitial) { createAndLoadInterstitial() } func showAd(_ viewController: UIViewController) { if interstitial.isReady { interstitial.present(fromRootViewController: viewController) } } } - Add the following to your AppDelegate.swift file, it will configure the app for Admob ads and load the first interstitial so that it is ready to be displayed when you try to display the interstitial:
... import GoogleMobileAds @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { ... var appId = "[YOUR ADMOB APP ID GOES HERE]" func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { GADMobileAds.configure(withApplicationID: appId) adController.createAndLoadInterstitial() ... } ... } - From the view controller where you want to show your interstitial ad, make the following call:
adController.showAd(self)
Note:
For testing, you should use the testAdId as the adUnitID in InterstitialAd.swift, this is so that real ads are not displayed during testing. For release, switch to using adId.... included for brevity in ApplicationDelegate.swift code above
Swift 4 - How to share messages and images
There are many benefits of enabling sharing within your application:
- Free advertising for your app if users share from it on social media
- Better user experience
- Using recent iOS features to make the app feel more modern
func share(_ message: String , shareImage: UIImage) {
let share = [message, shareImage] as [Any]
let activityViewController = UIActivityViewController(
activityItems: share, applicationActivities: nil)
activityViewController.popoverPresentationController?
.sourceView = self.view
self.present(activityViewController, animated: true,
completion: nil)
}
Friday, 23 March 2018
Swift 4 - The app's Info.plist must contain an NSCameraUsageDescription key
As of iOS 10, some features require an entry in the Info.plist before access will be allowed. This is for privacy purposes.
You can read more about this setting on Apple's developer website.
To solve this issue add the following to your Info.plist:
You can read more about this setting on Apple's developer website.
To solve this issue add the following to your Info.plist:
<key>NSCameraUsageDescription</key> <string>[why you need camera access]</string>
Monday, 4 September 2017
C# - Automapper vs Factory Methods
When converting data from one model to another, there is often the thought over whether it would be beneficial to use automapper or whether factory methods should be used to explicitly convert between models. I'm going to explain what each of these is, and explain a couple of advantages and disadvantages of each.
If you are using Automapper with default mappings and refactor the name of the source/target model, then you won't necessarily know until runtime because it won't cause a compile time error. The issue is that if there is a rename of the property, automapper will no longer be able to map correctly. Whereas if you were to explicitly code the conversion, there would be a compile time error so you can identify the error earlier. The risk of this failed mapping occurring can be mitigated by unit testing the mapping.
A similar issue to this is that there is a lack of static analysis. For example, if you find all references of a property it may look like nothing is referencing that property so you may be tempted to remove it. However, automapper could be mapping to this property without you even realising.
Overall, Automapper is a well tested library that can save you time writing uninspiring conversion code, but there are downsides and different scenarios may mean that it is beneficial or not.
Of course, there is a reason the Automapper NuGet package exists and this is because the manual conversion is tedious and takes time that could be spent on other things. The manual conversion also means that there is more code sitting in your project. Additionally, with anything manual there is the chance of human error and 2 properties that don't actually align with each other could potentially be mapped. Your unit tests should pick this up though.
When trying to choose between Automapper and Factory methods, think about your code and how well the objects will map automatically without configuration. Secondly, consider the important of static analysis and compile time errors in your code. This isn't a one-size fits all comparison, it's case by case as to which will be beneficial!
Automapper
Automapper is a NuGet package that allows you to "get rid of code that mapped one object to another". It is convention based, and if there are a large number of properties that are identical on 2 classes it can save a lot of developer time converting between objects. It also means that less code can be written for this conversion... Yay! However, there are a couple of disadvantages that come with convention based as opposed to explicit programming, and Automapper is no exception!If you are using Automapper with default mappings and refactor the name of the source/target model, then you won't necessarily know until runtime because it won't cause a compile time error. The issue is that if there is a rename of the property, automapper will no longer be able to map correctly. Whereas if you were to explicitly code the conversion, there would be a compile time error so you can identify the error earlier. The risk of this failed mapping occurring can be mitigated by unit testing the mapping.
A similar issue to this is that there is a lack of static analysis. For example, if you find all references of a property it may look like nothing is referencing that property so you may be tempted to remove it. However, automapper could be mapping to this property without you even realising.
Overall, Automapper is a well tested library that can save you time writing uninspiring conversion code, but there are downsides and different scenarios may mean that it is beneficial or not.
Factory Methods
Factory methods allow you to explicitly convert between objects. Due to the explicit conversion, it is easy for developers working on the same project to see where values are coming from. This is because it is not hidden behind a library that the developer may or may not be familiar with. It is also easier to debug. If mapping is done incorrectly there will also be compile time errors which can help catch issues earlier.Of course, there is a reason the Automapper NuGet package exists and this is because the manual conversion is tedious and takes time that could be spent on other things. The manual conversion also means that there is more code sitting in your project. Additionally, with anything manual there is the chance of human error and 2 properties that don't actually align with each other could potentially be mapped. Your unit tests should pick this up though.
When trying to choose between Automapper and Factory methods, think about your code and how well the objects will map automatically without configuration. Secondly, consider the important of static analysis and compile time errors in your code. This isn't a one-size fits all comparison, it's case by case as to which will be beneficial!
Friday, 1 September 2017
C# - Extension Methods
Extension methods allow you to extend functionality of a specific type. It is a special kind of static method that you can call as if it were an instance method on the object of the specified type. Extension methods are simple to define and you can define them as follows:
using System;
public class Program
{
public static void Main()
{
string message = "Hello World";
Console.WriteLine(message.GetDatedMessage());
}
}
// Extension methods must be contained within a non-generic static class
public static class StringExtensions
{
// Extension methods must be static
// Extended object must be prefixed with this
public static string GetDatedMessage(this string message) {
return String.Format("{0}: {1}", DateTime.Now, message);
}
}
Visual Studio - How to generate a NuGet package on build
NuGet packages are extremely useful way to add libraries/components to your code base. This is similar to the traditional way of referencing DLLs except that you get notifications when there are updates.
You may find that if your code lives in separate Git repositories that if someone wants to use a project from one Git repo in another Git repo that they would need to download both. However, NuGet packages can be stored in a common location e.g. the NuGet Package Gallery which is available to all, or on a centralised private NuGet server. If you want to use a private NuGet server, you will need to add a package source in the NuGet package manager. You can do this by clicking the little cog next to "Package source".
Now for actually generating the NuGet package you can do this automatically on build, by opening a right clicking on a project and selecting properties. Then navigate to the "Package" tab and check "Generate NuGet package on build"
You may find that if your code lives in separate Git repositories that if someone wants to use a project from one Git repo in another Git repo that they would need to download both. However, NuGet packages can be stored in a common location e.g. the NuGet Package Gallery which is available to all, or on a centralised private NuGet server. If you want to use a private NuGet server, you will need to add a package source in the NuGet package manager. You can do this by clicking the little cog next to "Package source".
Now for actually generating the NuGet package you can do this automatically on build, by opening a right clicking on a project and selecting properties. Then navigate to the "Package" tab and check "Generate NuGet package on build"
Tuesday, 15 August 2017
iTunes Connect - Tracking Financials
Payments and Financial Reports
You can go here to review your confirmed sales for closed months. It will give you a breakdown by currency and an estimated conversion.Sales and Trends
This will show you a graph of your sales. You can see which apps have sold, and roughly how many proceeds you have.When will I get paid?
Payments for a lot of countries will be after you've earned $10 USD. Some countries require a minimum payment threshold of $150 USD. The payment will happen approximately 30-45 days after the financial reports for the month in which you reached the minimum payment threshold. The payment will be made to your designated bank. You can read more about it on Apple's "Getting Paid" Resources and Help page. If you meet these criteria and you haven't received a payment, you may want to check that your bank account details have been supplied under "Agreements, Tax, and Banking". You should also check that you have a valid contract with Apple as this will also cause payments to be held.Friday, 21 July 2017
C# - Encrypting the App.config
Sometimes when you are storing sensitive information in the App.config e.g. API keys or database connection strings, you don't want to store them in plain text. Fortunately, visual studio provides a command line tool that enables you to encrypt sections of your App.config. These are automatically decrypted by the ConfigurationManager when you try to access the settings.
It is best that you have a separate section from appSettings for your encrypted settings as this will mean you will be able to change plain-text settings e.g. API URLs or retry attempts, without having to go through the encryption process. To create this section your App.config before encryption could look as follows:
If your web.config existed in your C:\Encryption directory, it could be encrypted using the command:
- Create a copy of your App.config called web.config. This is because the command line tool you will use to encrypt your settings will look for a web.config.
- Open the Developer Command Prompt for VS
- Enter the following command:
aspnet_regiis -pef [section to encrypt] [path containing web.config]
- Copy the contents of the web.config into the App.config.
It is best that you have a separate section from appSettings for your encrypted settings as this will mean you will be able to change plain-text settings e.g. API URLs or retry attempts, without having to go through the encryption process. To create this section your App.config before encryption could look as follows:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="EncryptedSettings"
type="System.Configuration.NameValueSectionHandler" />
</configSections>
<startup>
<supportedRuntime version="v4.0"
sku=".NETFramework,Version=v4.5" />
</startup>
<appSettings>
<add key="RetryAttempts" value="3" />
</appSettings>
<EncryptedSettings>
<add key="username" value="username" />
<add key="password" value="password" />
</EncryptedSettings>
</configuration>
If your web.config existed in your C:\Encryption directory, it could be encrypted using the command:
aspnet_regiis -pef "EncryptedSettings" C:\EncryptionThis section of the App.config can be accessed from the code as follows:
string devUrl = string.Empty;
var settings = ConfigurationManager.GetSection("EncryptedSettings")
as NameValueCollection;
var username = settings["username"];
Thursday, 18 May 2017
C# - Asynchronicity and the Main Thread
When you call an asynchronous method from your Main method of a console application in C#, you may experience the situation where your program runs to completion without hitting breakpoints following an await. An example of this is below:
The reason for this is that when Main exits the program exists, and any outstanding async operations are cancelled along with it. This can be solved by changing
namespace ConsoleTests
{
class Program
{
static void Main(string[] args)
{
var content = Get(args[0]);
}
public static async Task Get(string url)
{
using (HttpClient client = new HttpClient()) {
HttpResponseMessage response = await client.GetAsync(url);
//Breakpoint set here
}
}
}
}
The reason for this is that when Main exits the program exists, and any outstanding async operations are cancelled along with it. This can be solved by changing
var content = Get(args[0]);to
var content = Get(args[0]).Wait();to block Main from exiting.
Tuesday, 9 May 2017
C# - Polling Service
The Code
Polling services can be incredibly useful for picking up when something has changed and performing some actions. This post will cover how to set one up in C#. Firstly, you will want to create a new project with type Windows Service in Visual Studio:You will then want to rename Service1.cs and all its references to be something more representative of your polling service. You will also want to update the name the polling service will appear with by clicking on Service1.cs to open the designer, and then right click within the designer and choose "Properties", then update ServiceName in the Properties view.
In order to view the code backing the polling service you can click on "click here to switch to code view" from within the designer. This code should look something like this:
using System.ServiceProcess;
using System.Timers;
public partial class Service1 : ServiceBase
{
private Timer _timer;
public Service1()
{
InitializeComponent();
// Instantiating timer with 1000ms
// Every 1000ms the handler specified against _timer.Elapsed
/// will be called.
_timer = new Timer(1000);
_timer.Elapsed += ProcessThings;
}
private void ProcessThings(object sender, ElapsedEventArgs e)
{
// What you want to poll for
}
protected override void OnStart(string[] args)
{
_timer.Start();
}
protected override void OnStop()
{
_timer.Stop();
}
}
You can put whatever you want in ProcessThings but personally, I add a console application project to the solution that handles all of the processing. This way I can debug it at will without the need to install the polling service/wait for the polling period.
Installation
Click on Service1.cs, then right click and choose "Add Installer", you can name serviceProcessInstaller1 and serviceInstaller1 whatever you like. Click on serviceProcessInstaller1 and select what account you would like the polling service to run with, I chose Local System which is quite common, and means that it is using the local user's account. After this you can build your project. To install it open the Developer Command Prompt for VS 2017 as an administrator and then navigate to where the .exe of your project is.You can install using the following command:
installutil /i WindowsService1.exe
Alternatively, you can uninstall using the following command:
installutil /u WindowsService1.exe
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.
JSX
JavaScript and ECMAScript
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 BabelJSX
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.
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.
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.
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 ControlMonday, 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:
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.
Subscribe to:
Posts (Atom)