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
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
// 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
// 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
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;
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
/repository
/model
IUser.tsx
UserRepository.tsx
/repository
/model
IUser.tsx
UserRepository.tsx
/repository /model IUser.tsx UserRepository.tsx
// 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 }
// 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
// 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
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
Leave a Reply