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