React Native – All about architecture

Project structure

src\
components\
config\
modules\
network\
state\

How to avoid relative path when importing library (1)?

Install dependencies

yarn add metro-react-native-babel-preset --dev
yarn add babel-plugin-module-resolver --dev
// babel.config.js
{
  "presets": ["module:metro-react-native-babel-preset"],
  "plugins": [
    [
      "module-resolver",
      {
        "alias": {
          "@components": "./src/components",
          "@screens": "./src/screens"
          // Add more aliases as needed
        }
      }
    ]
  ]
}

Set vscode jump to correct component

  // tsconfig.json

  "compilerOptions": {
    ...
    "baseUrl": ".",
    "paths": {
      "src/*": ["./src/*"],
      "@components/*": ["./src/components/*"],
      "@screens/*": ["./src/screens/*"]
    },
    ...
  },

Navigation

If you create navigation from Component 1 to Component 2

  • Create a middle component
  • Create navigation to this middle component
  • Middle component will render component 2
import { useNavigation } from '@react-navigation/native';
...

const Component1: React.FC<Props> = () => {
  const navigation = useNavigation();
  const onPress = () => {
    navigation.navigate('ToSessionDetail', {
      usrName: usrName,
      id: id
    });
  }
  
  ...
  
  return ...
};

export default ToScanResult;
import React from 'react';
import Component2 from '.';

/////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////

interface Props {
  route: any;
}

const ToComponent2: React.FC<Props> = ({ route }) => {
  const { usrName, id } = route.params;
  return <Component2 usrName={usrName} id={id} />;
};

export default ToComponent2;

MVP

Model

  • Define object model
  • Get/ update server data
/repository
    /model
        IUser.tsx
    UserRepository.tsx
// IUser.tsx
export interface IUser {
  firstName?: string;
  lastName?: string;
  avatar?: string;  // image url
}
// UserRepository.tsx
const onSuccess = () => {
...
}

const onFailure = () => {
...
}

export const getUserList = async ( ... ) => {
    // Fetch data from server
    const list = await fetchUserList();

    // Format data into wanted format, combining with model format
    ...

    // Return data
    return formattedData
}

export const getUserDetail = async ( ... ) => {
    // Fetch data from server
    ...

    return formattedUserDetail;
}

View

  • Render UI
  • Update UI via Presenter
  • Deal with server data via Presenter
// UserListModal.tsx

export default const UserListModal = ({ navigation, isOpenModal, setIsOpenModal }) => {
  React.useEffect(() => {
    // Talk to Presenter
    Presenter.getUserList();
  }, []);

  const [userList, setUserList] = useState([]);

  // Tap on a user
  const onSelectUser = (user) => {
      Presenter.onSelectUser(user);
  };

  return (
        <MyModal
          isOpen={isOpenModal}
          setIsOpen={setIsOpenModal}
        >
            {userList.map((item, index) => {
              return (
                <ListItem
                  onPress={() => {
                    onSelectUser(item);
                  }}
                >
                  <Text>{item.userName}</Text>
                </ListItem>
              );
            })}
        </MyModal>
  );
}

Presenter

  • Deal with user interaction to
    • Get server data from Model
    • At the same time, update UI via View if necessary
export const getUserList = async ( ... ) => {
    // Show progress bar via View
    View.showProgressBar();

    // Get data from Model 
    const userList = await Model.getUserList( ... );

    // Update UI via View
    View.setUserList(userList);

    // Hide 
    View.hideProgressBar();
}

export const onSelectUser = async ( ... ) => {
    // Show progress bar via View
    View.showProgressBar();

    // Get data from Model
    const userDetail = await Model.getUserDetail( ... );

    // Navigate to UserDetail screen
    navigation.navigate('Detail', user: userDetail);

    // Hide 
    View.hideProgressBar();
}

State

Context API

  • App state
  • Module state
  • Screen state
  • Functional state

Why can’t you give up Redux?

Need to use Redux Persist because there is no solution to persist state when force closing the app

Be the first to comment

Leave a Reply

Your email address will not be published.


*