GithubHelp home page GithubHelp logo

rn-mini's Introduction

React Native Course

React Native is a port of React to build native applications on iOS and Android. It differs from some other cross-platform frameworks in that it uses native views rather than a webview. JavaScript code is executed in a separate thread from the UI to ensure animations are smooth and the app stays responsive.

If you have experience in React, then React Native will seem intuitive. In fact, the same core JavaScript library is used. React Native just uses a different renderer than ReactDOM and instead renders to native iOS and Android components.

More details can be found at https://facebook.github.io/react-native/

Your mission...

...should you choose to accept it, is building a location-aware weather app. Display the nearest city name, temperature, description of conditions, and an icon representing those conditions.

Weather App Preview

Setup

The API we'll be using to fetch weather information from is weatherbit.io. Accounts can take a few minutes to provision, so signing up now will ensure it's available when needed.

After signing up, you'll receive an API key in your email. Hang on to this.

Start with a Snack

Snack is an in-browser environment for prototyping React Native applications. Think of it as similar to JSFiddle, but specifically for React Native. We'll be using this to jump-start our learning experience.

When you arrive, you'll be prompted with a QR code and instructions to install the Expo app. You can skip this for now, as Snack also provides in-browser emulators for both iOS and Android.

To enable the in-browser emulator, toggle "Preview", and click "Tap to Play".

Now that your app is running, let's start coding.

You seem familiar

Right away, you'll notice that the example code looks like a normal React component, a class extending React.Component. Something's different about the JSX though. Where are the <div> tags?

Because we're not rendering to the browser, we use <View> tags that are an abstraction over iOS's UIView, Android's android.view (and possibly even <div>!). A View is just a container.

<Text> is a component to render text output. Unlike React for web, rendered text must be placed within a <Text> component. It can be thought of as similar to a <span>.

Update the content of the <Text> tag to "Hello!" and watch the app refresh to reflect your change.

<View style={styles.container}>
  <Text style={styles.paragraph}>
    Hello there!
  </Text>
</View>

Now you're styling

React Native doesn't have css files, but instead has a feature called StyleSheet. A StyleSheet is an object that takes properties similar to css, but using camelCase instead of dash-case. Styles are then assigned to components through the style attribute. An example already exists within the project.

You can also use inline styles directly in the style attribute, but Stylesheet offers a more performant and organized way of managing styles. Multiple sets of styles can be applied by passing an array to style (ex: style={[styles.title, styles.main, {fontSize: 20}]}).

Change the color and fontSize properties of the paragraph style and watch the change be reflected in your emulator.

Fake it 'til you make it

Let's start building our weather app by creating a Display component. It will show four pieces of information. Take them in as props.

  • temperature
  • description
  • city
  • state

Like any weather app, temperature should be large and prominent.

Within App, replace the example JSX with a Display component with hardcoded data.

<View style={styles.container}>
  <Display
    temperature={85}
    description={'Hazy'}
    city={'Provo'}
    state={'UT'} />
</View>

Requesting backup

Still have your weatherbit.io key from earlier? Add it as a variable in the file.

const KEY = 'abc123';

We'll start by using Weatherbit's postal API that will take a zip code and look up the current weather. React Native provides the standard fetch for making http requests.

Add a componentDidMount to App and hit the endpoint including your key. console.log the response to take a look at what we're getting back.

componentDidMount() {
  fetch(`https://api.weatherbit.io/v1.0/current/postal?country=US&postal_code=84044&units=I&key=${KEY}`)
    .then(res => res.json())
    .then(json => console.log(json))
}

units=I returns imperial metrics instead of metric.

To prevent rate limiting: replace https://api.weatherbit.io with https://weatherbitproxy-hbpqeytmef.now.sh, a cached proxy of weatherbit's API.

Getting real

After knowing the shape of the response, it can be used to show real data in the Display component.

The response has a data array with only one item in it. Wrap that and set it to state.

.then(json => {
  this.setState({
    current: json.data[0]
  });
});

Now that actual weather data is in state, it can be used within the App render method. Wire up the Display props.

<Display
  temperature={this.state.current.temp}
  ...
  />

Picture this

Weatherbit offers a set of icons to represent the current conditions. Using the current.weather.icon field, we can build a url for the corresponding icon.

https://www.weatherbit.io/static/img/icons/${code}.png

Add an Image component to the Display component. Make it 120x120.

<Image
  source={{uri: `ICON_URL_HERE`}}
  style={styles.icon} />

Getting local

Hardcoding a postal code works for testing the API, but we're on mobile devices with geolocation sensors. Let's use those to retrieve more accurate weather.

React Native includes a polyfill for the browser navigator.geolocation API. It abstracts over the iOS and Android specific calls. When using geolocation, the user will be prompted for location access.

navigator.geolocation.getCurrentPosition(
  position => console.log(position),
  err => console.error(err),
  {timeout: 2000}
)

getCurrentPosition is asynchronous, and it takes 2 callbacks, one for a success, and another for failure. On success, position.coords holds the latitude and logitude of our current position.

Note: The timeout is necessary for the in-browser emulator. The emulated device waits to resolve a position, causing neither success or failure callbacks to get called. The timeout forces the error callback to get invoked after 2 seconds. Shim it by returning an default position of American Fork:

{coords: { latitude: 40.4, longitude: -111.8 }};

Weatherbit has a /current endpoint that supports lat and lon. Change your fetch call to use it instead of postal code.

https://api.weatherbit.io/v1.0/current?key=${key}&units=I&lat=${position.coords.latitude}&lon=${position.coords.longitude}

Stats for nerds

The weather API returns various other stats that our app can list below the title. Create a Stat component to show a stat like Wind Direction on the left and SW on the right. flexDirection: row and flex: 1 will help with this.

const Stat = ({ title, value }) => (
  <View style={styles.stat}>
    <Text style={styles.statTitle}>{title}</Text>
    <Text>{value}</Text>
  </View>
);

Add a few stats to a <View> styled with flex: 1 in the App component

<View style={styles.stats}>
  <Stat title="Wind Direction" value={current.wind_cdir} />
  <Stat title="Wind Speed" value={`${current.wind_spd} MPH`} />
  <Stat title="Visibility" value={current.visibility} />
  <Stat title="Pressure" value={`${current.pres} Hg`} />
  <Stat title="Humidity" value={`${current.rh}%`} />
  <Stat title="Timezone" value={current.timezone} />
</View>

Scroll

Did you notice that the stats list isn't scrollable? When in React Native, you explicitly choose when something should scroll by using the ScrollView component.

Import it and replace the <View> from the last step with <ScrollView>.

Congrats! you've built a basic cross-platform, location-aware, realtime weather app.

Extras

Making promises

navigator.geolocation.getCurrentPosition is awkward because it is callback based. We can wrap it with a Promise to take advantage of Promise chaining.

const getPosition = options => new Promise((resolve, reject) => {
  navigator.geolocation.getCurrentPosition(resolve, reject, options);
});

This promise will resolve when a position is successfully found and reject when an error occurs.

It now allows us to write readable async code as follows:

getPosition({timeout: 2000})
  .catch(() => ({coords: { latitude: 40.4, longitude: -111.8 }}))
  .then(position => fetch(...))
  .then(res => res.json())
  .then(json => {
    this.setState({current: json.data[0]});
  });

They don't stop

While looking up location and making a request, a loading spinner can improve the user experience over a blank screen.

React Native includes a built-in ActivityIndicator component. Import it, and render it while state.current is null.

if (!state.current) {
  return <ActivityIndicator size="large" style={{flex: 1}} />
}

rn-mini's People

Contributors

statianzo avatar

Stargazers

 avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.