์ฐ์ React Native์์ ์น๋ทฐ๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด์
react-native-webivew ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ต๋๋ค.
RN | Webview | |
๋ฉ์์ง ๋ณด๋ผ ๋ | webviewRef.current.postMessage(JSON.stringify(message)); | window.ReactNativeWebView?.postMessage(JSON.stringify(message)); |
๋ฉ์์ง ๋ฐ์ ๋ | WebView ์ปดํฌ๋ํธ์ onMessage ์์ฑ์ ์ฌ์ฉํฉ๋๋ค |
//์๋
document.addEventListener('message', getMessageListener); //ios window.addEventListener('message', getMessageListener);
|
RN์์ ์ฌ์ฉํ๋ ์
ref๋ฅผ ์ฌ์ฉํด์ webview์ postMessage ๋ฉ์๋๋ฅผ ์ด์ฉํฉ๋๋ค
๋ฉ์์ง๋ฅผ ๋ณด๋ผ ๋๋ string๋ง ๋ณด๋ผ ์ ์๊ธฐ ๋๋ฌธ์
JSON.stringify๋ก ๋ฉ์์ง ๊ฐ์ฒด๋ฅผ ์คํธ๋ง์ผ๋ก ๋ณํํฉ๋๋ค
์น๋ทฐ๋ก๋ถํฐ 'WEBVIEW_LOADED_MESSAGE_TYPES' ํ์ ์ ๋ฉ์์ง๋ฅผ ๋ฐ์ผ๋ฉด ํ ํฐ์ ์ ์กํ๋ ์ฝ๋์ ๋๋ค
const HomePage = () => {
const navigation = useNavigation<RootNavigatonProp>();
const webviewRef = useRef<WebView | null>(null);
const [token] = useRecoilState(tokenState);
const postMessage = (message: MessageTypes) => {
if (!webviewRef.current) return;
webviewRef.current.postMessage(JSON.stringify(message));
};
return (
<SafeAreaView style={{width: '100%', height: '100%'}}>
<WebView
ref={webviewRef}
source={{uri: WEBVIEW_URI_DEV}}
style={{flex: 1, width: '100%', height: '100%'}}
onMessage={ev => {
const {type, payload} = JSON.parse(
ev.nativeEvent.data,
) as MessageTypes;
switch (type) {
case 'WEBVIEW_LOADED_MESSAGE_TYPES':
if (token) postMessage(onLoginSuccessMessage(token));
break;
case 'NAVIGATE_MESSAGE_TYPES':
navigation.push(payload.stack, payload.params);
break;
}
}}
/>
</SafeAreaView>
);
};
export default HomePage;
์น๋ทฐ(Next)์์ ์ฌ์ฉํ๋ ์
1. ์ปดํฌ๋ํธ๊ฐ ๋ง์ดํธ ๋๋ฉด ํ์ด์ง๊ฐ ๋ก๋๋๋ค๋ ๋ฉ์์ง๋ฅผ RN์ผ๋ก ์ ์กํฉ๋๋ค
2. RN์ผ๋ก๋ถํฐ 'LOGIN_SUCCESS_MESSAGE_TYPES' ํ์ ์ ๋ฉ์์ง๋ฅผ ๋ฐ์ ๊ฒฝ์ฐ payload์ ๋ด๊ฒจ์๋ ํ ํฐ์ ์ ์ฅํฉ๋๋ค
'use client';
import { tokenState } from '@/store/loginAtom';
import {
MessageTypes,
postMessageToWebview,
webviewLoadedMessage,
} from '@/utils/message';
import { ReactNode, useCallback, useEffect } from 'react';
import { useSetRecoilState } from 'recoil';
const MessageWrapper = ({ children }: { children: ReactNode }) => {
const setToken = useSetRecoilState(tokenState);
const getMessageListener = useCallback((event: any) => {
if (typeof event.data !== 'string') return;
const eventData = JSON.parse(event.data) as MessageTypes;
switch (eventData.type) {
case 'LOGIN_SUCCESS_MESSAGE_TYPES':
setToken(eventData.payload);
}
}, []);
useEffect(() => {
document.addEventListener('message', getMessageListener);
window.addEventListener('message', getMessageListener);
postMessageToWebview(webviewLoadedMessage());
return () => {
document.removeEventListener('message', getMessageListener);
window.removeEventListener('message', getMessageListener);
};
}, []);
return <div>{children}</div>;
};
export default MessageWrapper;
๊ฐ ๋ฉ์์ง๋ค์ ํจ์๋ก ๋ง๋ค์ด์ ์ฌ์ฉํฉ๋๋ค
type์ as const๋ฅผ ์ฌ์ฉํด์ ๊ทธ ์์ฒด๋ก ํ์ ์ ์ธ์ ๋ฐ๋๋ก ํ์ต๋๋ค
import {TabStackParamList} from '@/routes/TabNavigation';
import {TokenType} from '@/types/auth.types';
import {AllScreenParamsType, MainStackParamList} from '@/types/navigation.type';
import {NativeStackNavigationProp} from '@react-navigation/native-stack';
export const webviewLoadedMessage = () => ({
type: 'WEBVIEW_LOADED_MESSAGE_TYPES' as const,
payload: {},
});
export const onBackPressedMessage = () => ({
type: 'BACK_PRESSED_MESSAGE_TYPES' as const,
payload: {},
});
export const onExitAppMessage = () => ({
type: 'EXIT_APP_MESSAEG_TYPES' as const,
payload: {},
});
export const onLoginSuccessMessage = (token: TokenType) => ({
type: 'LOGIN_SUCCESS_MESSAGE_TYPES' as const,
payload: token,
});
export const logoutMessage = () => ({
type: 'LOGOUT_MESSAGE_TYPES' as const,
payload: {},
});
export const navigateMessage = (
stack: keyof MainStackParamList | keyof TabStackParamList,
params: AllScreenParamsType,
) => ({
type: 'NAVIGATE_MESSAGE_TYPES' as const,
payload: {stack, params},
});
export type MessageTypes =
| ReturnType<typeof webviewLoadedMessage>
| ReturnType<typeof onBackPressedMessage>
| ReturnType<typeof onExitAppMessage>
| ReturnType<typeof onLoginSuccessMessage>
| ReturnType<typeof logoutMessage>
| ReturnType<typeof navigateMessage>;
์ฐธ๊ณ
https://velog.io/@imzzuu/React-Native-%EC%9B%B9%EB%B7%B0-%ED%86%B5%EC%8B%A0%ED%95%98%EA%B8%B0
'๐ป ํ๋ก ํธ์๋' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[CSS] aspect-ratio ์์ด ์์ ๋น์จ ์ ์งํ๊ธฐ (0) | 2024.08.11 |
---|---|
Next scss ์ ์ญ๋ณ์ ์ ์ฉํ๊ธฐ (0) | 2024.01.17 |
React Native ์น์์ผ ์ฑํ ๊ตฌํ (1) | 2024.01.10 |
CSS ์์ ์์๊ฐ focus ๋ ๋ ๋ถ๋ชจ ์์ ํจ๊ณผ ์ฃผ๊ธฐ (2) | 2024.01.08 |
React Native์ React ์ปดํฌ๋ํธ ์ฐจ์ด (2) | 2024.01.08 |