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
Leave a Reply