Let’s add a React Native JSX component to your app.
Open MyApp/index.youi.js
in your editor and import the Button
component from React Native.
Add a simple button press handler onMyButtonPress
above the render function.
You can use console.log
to help with app debugging.
Console log output appears in the terminal window where you start your app.
Make use of the new button handler by adding a button to your app.
Create a new View
below the View Image
is contained within.
Give it the style buttonContainer
(we’ll create that in a moment).
In this view, add the button with a title
and an onPress
handler.
Now, add the buttonContainer
style to the Stylesheet defined at the bottom of index.youi.js
.
Like Facebook RN apps, You.i Platform apps can be made accessible. You can add accessibility information to your app to support screen reading functionality.
We support screen reader functionality for the following target platforms:
To learn more, see Accessibility.
Let’s go back to the button you added earlier and update it with accessibility props.
<View style={styles.buttonContainer}
focusable={true}
accessible={true}
accessibilityLabel="My button"
accessibilityHint="Button in your first app"
accessibilityRole="button"
>
<Button
onPress={this.onMyButtonPress}
title="My button"
/>
</View>
Run your application again to see the button you just added.
There’s not much to the button yet, but you’ll remember that we added a button handler. Try clicking it a few times.
Now, switch back to the terminal window you used to launch your app. Review the console log output to see if you can find your button handler’s log messages.
***** You keep pressing my buttons. Stop it! *****
The log messages tell us that your new button is working. If you don’t see the log messages, double-back and check your work before moving on.
Next, let’s add a bit of fun to the application by adding a light and dark mode.
To do this, we’ll make use of a new custom Button
component and a couple more styles.
Here’s a quick GIF demonstrating what we’re going to build.
Before getting started, you should restore the You.i TV logo or have a light and dark version of the image you’ve selected.
As a reminder, the original You.i TV logo filename is youi_logo_red.png
.
Let’s use a state variable to track the current theme state: light or dark.
Add the lightTheme
variable to your app as shown below.
We want the app to change from dark to light mode (or vice versa) whenever the button is pressed.
After adding the state, modify the onMyButtonPress
handler to reverse the state of lightTheme
.
And while we’re in there, let’s make it print a more useful log message.
...
export default class YiReactApp extends Component {
state = {
lightTheme: true
};
onMyButtonPress = () => {
this.setState({
lightTheme: !this.state.lightTheme
});
console.log('***** Changing theme to: ' + (this.state.lightTheme ? 'dark' : 'light' ) + ' *****');
};
Until now, our button’s label has been My Button
(unless you got more creative with yours).
Let’s update the button to indicate what it does when it’s pressed.
Start by destructuring lightTheme
from the state.
render() {
const { lightTheme } = this.state;
Then, use this value to update the button’s title
to reflect the expected result of pressing it.
return (
...
<Button
onPress={this.onMyButtonPress}
title={`Switch to the ${lightTheme ? "dark" : "light"} theme`}
/>
...
}
Give it a test. Switch back to your app and click the button a few times. With each click, the button text changes. And your console log messages now reflect the theme mode changes.
To simplify making a dark and light theme, we have a custom style sheet with the colors already defined.
Copy and paste the following definitions into a new file called styles.js
, in the same location as index.youi.js
.
import { StyleSheet } from "react-native";
export const darkStyles = StyleSheet.create({
header: {
backgroundColor: "#000000"
},
button: {
backgroundColor: "#f1f1f1"
},
buttonText: {
color: "#000000"
},
body: {
backgroundColor: "#303030"
},
headlineText: {
color: "#f1f1f1"
},
bodyText: {
color: "#f1f1f1"
}
});
export const lightStyles = StyleSheet.create({
header: {
backgroundColor: "#ffffff"
},
button: {
backgroundColor: "#333333"
},
buttonText: {
color: "#ffffff"
},
body: {
backgroundColor: "#e6e7e7"
},
headlineText: {
color: "#333333"
},
bodyText: {
color: "#333333"
}
});
We’ve also created a custom Button
component.
Our new Button
includes a default focus state that we’ll make use of as we build out the theme mode.
Copy and paste the following into a new file called button.js
in the same folder as index.youi.js
and styles.js
.
import React from "react";
import { StyleSheet, Text, TouchableWithoutFeedback, View } from "react-native";
import { FocusManager } from "@youi/react-native-youi";
const Button = ({
buttonStyle,
defaultFocus,
onPress,
textStyle,
title
}) => {
return (
<TouchableWithoutFeedback
focusable={true}
accessible={true}
accessibleLabel={title}
onPress={onPress}
ref={ref => ref && defaultFocus && FocusManager.focus(ref)}
>
<View style={[styles.button, buttonStyle]}>
<Text style={[styles.buttonText, textStyle]}>{title}</Text>
</View>
</TouchableWithoutFeedback>
);
};
const styles = StyleSheet.create({
button: {
paddingHorizontal: 30,
paddingVertical: 10,
borderRadius: 5
},
buttonText: {
fontSize: 20
}
});
export default Button;
Modify index.youi.js
to import the new custom Button
component and the style sheets you just created in styles.js
.
Be sure to remove the previous react-native Button
import.
import React, { Component } from "react";
import { AppRegistry, Image, SafeAreaView, StyleSheet, Text, View } from "react-native";
import { FormFactor } from "@youi/react-native-youi";
import Button from './button.js';
import { lightStyles, darkStyles } from './styles.js';
...
Let’s configure Button
to get both the button’s style and associated button text style from our new style sheets.
Add two new props, textStyle
and buttonStyle
to Button
in index.youi.js
.
Configure these so they set the button’s styling based on the currently selected theme.
While you’re in there editing Button
, you can also update it to use the defaultFocus
prop.
To give the button focus when the app starts, set defaultFocus
to true.
The new button component in your app looks like this:
render()
...
<Button
onPress={this.onMyButtonPress}
title={`Switch to the ${lightTheme ? "dark" : "light"} theme`}
textStyle={lightTheme ? lightStyles.buttonText : darkStyles.buttonText}
buttonStyle={lightTheme ? lightStyles.button : darkStyles.button}
defaultFocus={true}
/>
If your application is already running, when you save these changes the application will refresh automatically.
At this point, your application should look like this. When you press the button, the text and style change. Next, we’ll add in the rest of the dark theme.
You may see stats at the top and bottom of your window (such as frame rate).
You can hide these from the Dev Panel.
Triple-click in any corner of the window to show the Dev Panel.
Click the Toggle HUD
button to turn off the heads up display (HUD).
When you’re done, click anywhere outside the Dev Panel to close it.
To implement the theme switch, we’ll use a function that provides the name of the style sheet to use (lightStyles or darkStyles).
Add a new getTheme
function near the bottom of index.youi.js
.
...
});
function getTheme(lightTheme) {
return lightTheme ? lightStyles : darkStyles;
}
AppRegistry.registerComponent("YiReactApp", () => YiReactApp);
Before rendering, the app can check which style to apply, by calling your new function.
In your main render()
function, add a new constant themeStyles
that retrieves the current theme.
render() {
const { lightTheme } = this.state;
const themeStyles = getTheme(lightTheme);
return (
...
Now, update headerContainer
, bodyContainer
, headlineText
, and bodyText
to use a combination of the original style and the current theme style (themeStyles.<x>
) as shown below.
Styles are applied left to right.
We use this to our advantage to define new colors in lightStyles
and darkStyles
.
These styles override the colors from the original styles
but the rest of the component styling remains common.
return (
<SafeAreaView style={styles.mainContainer}>
<View style={[styles.headerContainer, themeStyles.header]}>
...
<View style={[styles.bodyContainer, themeStyles.body]} focusable={true} accessible={true}>
<Text
style={[styles.headlineText, themeStyles.headlineText]}
accessibilityLabel="Welcome to your first You I React Native app"
>
Welcome to your first You.i React Native app!
</Text>
<Text
style={[styles.bodyText, themeStyles.bodyText]}
>
For more information on where to go next visit
</Text>
<Text
style={[styles.bodyText, themeStyles.bodyText]}
accessibilityLabel="https://developer dot you i dot tv"
>
https://developer.youi.tv
</Text>
</View>
...
accessibilityLabel
suppresses the text of the node itself and lets you control what’s read aloud.
You’ll notice we’re using this technique above to have the screen reader read out our website address correctly.
If you kept your own logo in the app instead of the You.i TV logo, get a “dark mode” copy of that logo and put it in <AppName>/youi/AE/assets/drawable/default
.
If you’re using the You.i TV logo, right-click and download this You.i TV dark mode logo.
Save it in <AppName>/youi/AE/assets/drawable/default/
.
Update index.youi.js
to be aware of both versions of your image (lightImage
and darkImage
).
Then alter Image
’s source to change the picture dynamically, by selecting the correct image based on the theme.
Remember to use your file names if not using the You.i TV logo.
render() {
const { lightTheme } = this.state;
const themeStyles = getTheme(lightTheme);
const lightImage = "youi_logo_red.png";
const darkImage = "youi_logo_white.png";
...
<Image
style={styles.image}
source={{ uri: `res://drawable/default/${lightTheme ? lightImage : darkImage}` }}
/>
...
You’ve added a new asset, so you need to rebuild your application to get the new image copied into your target folder.
youi-tv build -p osx
youi-tv build -p linux
youi-tv build -p win64
Then run your app again to see the full dark mode toggle in action!
./youi/build/osx/Debug/MyApp
./youi/build/linux/Debug/bin/MyApp
./youi/build/uwp/Debug/MyApp
Now you have a working app that uses basic React Native components and a custom component.
Next up, let’s take a look at some automated tests for your application.