techStackGuru

React Native Design Patterns


As a popular framework for developing cross-platform mobile applications, React Native incorporates various design patterns that improve code structure, maintainability, scalability, and overall development experience. These are some of the most common design patterns used in React Native.


1. Component-based Architecture

An important feature of React Native is that it follows a component-based architecture, where UI components are broken down into reusable parts. By doing so, code reusability and maintainability are promoted.

App.js
// App.js
import React from 'react';
import { View } from 'react-native';
import Header from './Header';
import TodoList from './TodoList';
import Footer from './Footer';

const App = () => {
  return (
    <View>
      <Header />
      <TodoList />
      <Footer />
    </View>
  );
}

export default App;
Header.js
// Header.js
import React from 'react';
import { View, Text } from 'react-native';

const Header = () => {
  return (
    <View>
      <Text>Todo List</Text>
    </View>
  );
}

export default Header;
TodoItem.js
// TodoItem.js
import React from 'react';
import { View, Text } from 'react-native';

const TodoItem = ({ text }) => {
  return (
    <View>
      <Text>{text}</Text>
    </View>
  );
}

export default TodoItem;
TodoList.js
// TodoList.js
import React from 'react';
import { View } from 'react-native';
import TodoItem from './TodoItem';

const TodoList = () => {
  const todoItems = [
    { id: 1, text: 'Buy groceries' },
    { id: 2, text: 'Finish homework' },
    { id: 3, text: 'Call mom' }
  ];

  return (
    <View>
      {todoItems.map(item => (
        <TodoItem key={item.id} text={item.text} />
      ))}
    </View>
  );
}

export default TodoList;
Footer.js
// Footer.js
import React from 'react';
import { View, Text } from 'react-native';

const Footer = () => {
  return (
    <View>
      <Text>Footer</Text>
    </View>
  );
}

export default Footer;

As shown in this example, each component (Header, TodoItem, TodoList, and Footer) handles a specific part of the user interface.TodoList components dynamically render TodoItem components based on the data they are passed. Component-based architecture provides the benefit of easy management, understanding, and maintenance of code, due to its modular approach.

2. Container-View Pattern

  • A container separates presentation from logic and data (View).
  • Data and logic are received from Container through props.
  • // Container.js
    function UserContainer(props) {
      const { user, fetchUser } = props;
    
      useEffect(() => {
        fetchUser();
      }, []);
    
      return <UserView user={user} />;
    }
    
    // UserView.js
    function UserView({ user }) {
      return (
        <View>
          <Text>Name: {user.name}</Text>
          <Text>Email: {user.email}</Text>
        </View>
      );
    }

    3. Higher-Order Components (HOC):

    This pattern involves a function taking a component and returning a new component that has more functionality.

    import React from 'react';
    import { TouchableOpacity } from 'react-native';
    
    const withBackgroundColor = (WrappedComponent, color) => {
      return (props) => (
        <TouchableOpacity style={{ backgroundColor: color }}>
          <WrappedComponent {...props} />
        </TouchableOpacity>
      );
    };
    
    const MyButton = ({ onPress }) => (
      <TouchableOpacity onPress={onPress}>
        <Text>Click me</Text>
      </TouchableOpacity>
    );
    
    export default withBackgroundColor(MyButton, 'blue');

    4. Render Props:

    In this pattern, the logic of a component is encapsulated into a function prop.

    import React from 'react';
    import { View, Text } from 'react-native';
    
    const RenderPropsComponent = ({ render }) => {
      return (
        <View>
          {render && render()}
        </View>
      );
    };
    
    const App = () => (
      <RenderPropsComponent
        render={() => (
          <Text>Hello, Render Props!</Text>
        )}
      />
    );
    
    export default App;

    5. Flux/Redux:

    This pattern helps manage application state by creating predictable state containers.

    import React from 'react';
    import { View, Text } from 'react-native';
    
    const RenderPropsComponent = ({ render }) => {
      return (
        <View>
          {render && render()}
        </View>
      );
    };
    
    const App = () => (
      <RenderPropsComponent
        render={() => (
          <Text>Hello, Render Props!</Text>
        )}
      />
    );
    
    export default App;