Back to blog

Using NativeBase v3 the Right Way

Rohit Singh· Software Engineer·October 17, 2021·5 min read
Using NativeBase v3 the Right Way

Since the release of NativeBase v3, many developers have adopted the framework to build applications. As a library co-creator, the team became curious about community usage patterns, leading them to gather feedback. They discovered that many developers weren't leveraging v3's full capabilities or assumed it would be overly complicated. This prompted them to create an introductory guide demonstrating the simplicity of NativeBase's approach to building beautiful and efficient UIs.

The guide covers six key segments.

Setting up your project

For new projects using NativeBase, the team recommends leveraging example templates provided with the component library. These templates accelerate setup and demonstrate light and dark mode implementation along with custom theme configuration.

Expo Project:

npx create-native-app -t with-nativebase

Create React App Project:

npx create-react-app myapp && cd myapp && npm install native-base

React Native Project:

npx @react-native-community/cli@latest init MyApp --template native-base

Next.js Project:

npx create-next-app --example with-nativebase

"All the templates on NativeBase v3 come with a customTheme setup using which you can customise themes very easily."

Utility Props vs StyleSheet API

The team strongly recommends using Utility Props over StyleSheets wherever possible. NativeBase components accept numerous utility props that enhance code clarity and maintainability.

Using the React Native StyleSheet approach:

import * as React from "react";
import { Text, View, StyleSheet } from "react-native";
 
export default function App() {
  return (
    <View style={styles.container}>
      <View style={styles.card}>
        <View style={styles.row}>
          <Text style={styles.subHeading}>Business</Text>
          <Text style={styles.period}>1 month ago</Text>
        </View>
        <Text style={styles.heading}>Marketing License</Text>
        <Text style={styles.paragraph}>
          Unlock powerfull time-saving tools for creating email delivery and
          collecting marketing data
        </Text>
        <Text style={styles.link}>Read More</Text>
      </View>
    </View>
  );
}
 
const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: "center",
    alignItems: "center",
    backgroundColor: "#374151",
  },
  card: {
    width: 296,
    backgroundColor: "#f9fafb",
    padding: 20,
    borderRadius: 8,
  },
  paragraph: {
    marginTop: 8,
    fontSize: 14,
    fontWeight: "medium",
    color: "#6b7280",
  },
  period: {
    fontSize: 10,
    color: "#a1a1aa",
  },
  heading: {
    marginTop: 12,
    fontSize: 20,
    fontWeight: 500,
  },
  link: {
    marginTop: 8,
    color: "#0891b2",
    fontWeight: "medium",
    fontSize: 12,
  },
  subHeading: {
    fontSize: 12,
    color: "#71717a",
  },
  row: {
    flexDirection: "row",
    justifyContent: "space-between",
    alignItems: "flex-start",
  },
});

Expo Snack: https://snack.expo.dev/pu9jBPcut

Using NativeBase Utility Props:

import React from 'react';
import {
  Center,
  NativeBaseProvider,
  HStack,
  Box,
  Text,
  Spacer,
} from 'native-base';
 
export default () => {
  return (
    <NativeBaseProvider>
      <Center flex={1} bg="coolGray.700">
        <Box bg="blueGray.50" p="5" w="296" rounded="8">
          <HStack alignItems="flex-start">
            <Text fontSize="12" color="gray.500" fontWeight="medium">
              Business
            </Text>
            <Spacer />
            <Text fontSize="10" color="gray.400">
              1 month ago
            </Text>
          </HStack>
          <Text mt="3" fontWeight="medium" fontSize="20">
            Marketing License
          </Text>
          <Text mt="2" fontSize="14" color="gray.500">
            Unlock powerfull time-saving tools for creating email delivery and
            collecting marketing data
          </Text>
          <Text mt="2" fontSize="12" fontWeight="medium" color="cyan.600">
            Read More
          </Text>
        </Box>
      </Center>
    </NativeBaseProvider>
  );
};

Expo Snack: https://snack.expo.dev/AGNgFxZ4L

Advantages of Utility Props:

  • Massive productivity boost
  • Better code readability
  • No need to remember style names
  • Emphasis on creating reusable components instead of reusable stylesheets
  • Using Theme Tokens

Importing from a single source

NativeBase passed several common components from the core React Native library through its Factory function, allowing developers to import from a single source while accessing all NativeBase features.

Recommended components to import from NativeBase:

import {
  ScrollView,
  View,
  KeyboardAvoidingView,
  StatusBar,
  FlatList,
  SectionList,
} from "native-base";

Component documentation links:

  1. ScrollView
  2. View
  3. KeyboardAvoidingView
  4. StatusBar
  5. FlatList
  6. SectionList

Thinking in terms of pseudo props

NativeBase provides pseudo props that simplify the development experience significantly.

Color Mode Pseudo Props

NativeBase offers hooks to detect the current theme and color mode (Light or Dark), but this requires importing hooks, calling them, and conditionally checking the mode, which is a tedious process.

Instead, developers can use _light and _dark pseudo props, and NativeBase automatically applies them based on the relevant color mode.

Using conditional logic with hooks:

import React from "react";
import {
  Button,
  Center,
  useColorMode,
  NativeBaseProvider,
} from "native-base";
 
export function TestApp() {
  const { colorMode } = useColorMode();
  return (
    <Button
      bg={colorMode === "light" ? "primary.500" : "primary.400"}
      _text={colorMode === "light" ? { color: "primary.800" } : "white"}
    >
      Button
    </Button>
  );
}
 
export default () => {
  return (
    <NativeBaseProvider>
      <Center flex={1}>
        <TestApp />
      </Center>
    </NativeBaseProvider>
  );
};

Using pseudo props (_light and _dark):

import React from "react";
import { Button, Center, NativeBaseProvider } from "native-base";
 
export function TestApp() {
  return (
    <Button
      _light={{ bg: "primary.500" }}
      _dark={{ _text: { color: "primary.800" } }}
    >
      Button
    </Button>
  );
}
 
export default () => {
  return (
    <NativeBaseProvider>
      <Center flex={1}>
        <TestApp />
      </Center>
    </NativeBaseProvider>
  );
};

Platform Pseudo Props

Previously, developers had to use conditional logic based on Platform.OS to apply platform-specific props. NativeBase simplifies this with _web, _android, and _ios pseudo props.

Before:

<Input
  numberOfLines={Platform.OS === "android" ? "4" : null}
  width={Platform.OS === "web" ? "48" : "80%"}
/>

After:

<Input _android={{ numberOfLines: 4 }} _web={{ width: "48" }} width="80%" />

Platform props override other props when the particular platform is active, as they take precedence.

Utilising the hooks to the fullest

NativeBase provides several custom hooks to accelerate application development.

useDisclose Hook

import React from "react";
import {
  Modal,
  Button,
  Center,
  useDisclose,
  NativeBaseProvider,
} from "native-base";
 
function UseDiscloseExample() {
  const { isOpen, onOpen, onClose } = useDisclose();
  return (
    <>
      <Modal isOpen={isOpen} onClose={onClose}>
        <Modal.Content>
          <Modal.CloseButton />
          <Modal.Header fontSize="4xl" fontWeight="bold">
            Hello World
          </Modal.Header>
          <Modal.Body>
            Lorem ipsum dolor sit amet consectetur adipisicing elit. Quos quasi
            cupiditate expedita, ipsa corporis officia totam similique delectus!
            Debitis esse, ea blanditiis iste enim iure at odit fugiat autem.
            Accusamus?
          </Modal.Body>
          <Modal.Footer>
            <Button colorScheme="blue" mr={1}>
              Save
            </Button>
            <Button onPress={onClose}>Close</Button>
          </Modal.Footer>
        </Modal.Content>
      </Modal>
      <Button onPress={onOpen}>Open Modal</Button>
    </>
  );
}
 
export default function () {
  return (
    <NativeBaseProvider>
      <Center flex={1}>
        <UseDiscloseExample />
      </Center>
    </NativeBaseProvider>
  );
}

useBreakpointValue Hook

import React from "react";
import {
  Box,
  useBreakpointValue,
  NativeBaseProvider,
  Center,
} from "native-base";
 
function UseBreakpointValueExample() {
  const color = useBreakpointValue({
    base: "red.200",
    sm: "blue.200",
    md: "blue.200",
  });
  return (
    <Box bg={color} w={"100px"}>
      This is a box
    </Box>
  );
}
 
export default function () {
  return (
    <NativeBaseProvider>
      <Center flex={1}>
        <UseBreakpointValueExample />
      </Center>
    </NativeBaseProvider>
  );
}

Additional hooks documentation:

  1. useDisclose
  2. useBreakpointValue
  3. useClipboard
  4. useMediaQuery
  5. useTheme
  6. useToken
  7. useColorMode
  8. useColorModeValue
  9. useContrastText
  10. useAccessibleColors

Strict Mode

NativeBase v3 includes a Strict Mode configuration that helps maintain best practices throughout codebases. It accepts three values: error, warn, and off (default).

Strict Mode validates that all props receive proper token values from the theme by only accepting string values. This became important with version 3.2.0's new token additions.

Before (incorrect):

<Box p={4} mx={3} my="12px" bg="primary.400" width="50%">
    Hello World
</Box>

After (correct):

<Box p="4" mx="3" my="3" bg="primary.400" width="1/2">
    Hello World
</Box>

Conclusion

The guide demonstrates how to utilize NativeBase v3's latest features optimally. With recent improvements, NativeBase enables creation of accessible and customizable components. The library continues evolving with additional guides planned to help developers build beautiful applications.

Developers are encouraged to share experiments in the Discord community.

Originally published on dev.to by Rohit Singh.