React Native – All about architecture

Project structure

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

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

Install dependencies

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
yarn add metro-react-native-babel-preset --dev
yarn add babel-plugin-module-resolver --dev
yarn add metro-react-native-babel-preset --dev yarn add babel-plugin-module-resolver --dev
yarn add metro-react-native-babel-preset --dev
yarn add babel-plugin-module-resolver --dev
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// 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
}
}
]
]
}
// 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 } } ] ] }
// 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

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// tsconfig.json
"compilerOptions": {
...
"baseUrl": ".",
"paths": {
"src/*": ["./src/*"],
"@components/*": ["./src/components/*"],
"@screens/*": ["./src/screens/*"]
},
...
},
// tsconfig.json "compilerOptions": { ... "baseUrl": ".", "paths": { "src/*": ["./src/*"], "@components/*": ["./src/components/*"], "@screens/*": ["./src/screens/*"] }, ... },
  // 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
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
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 { 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 { 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;
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
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;
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;
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
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
/repository
/model
IUser.tsx
UserRepository.tsx
/repository /model IUser.tsx UserRepository.tsx
/repository
    /model
        IUser.tsx
    UserRepository.tsx
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// IUser.tsx
export interface IUser {
firstName?: string;
lastName?: string;
avatar?: string; // image url
}
// IUser.tsx export interface IUser { firstName?: string; lastName?: string; avatar?: string; // image url }
// IUser.tsx
export interface IUser {
  firstName?: string;
  lastName?: string;
  avatar?: string;  // image url
}
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// 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;
}
// 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; }
// 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
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// 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>
);
}
// 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> ); }
// 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
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
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();
}
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(); }
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.


*