React-Native 开发鸿蒙 NEXT-cookie 设置
应用有个积分商城,做一些积分兑换的业务,就一个基于 react-native-webview 开发的页面,在页面加载的时候通过 js 注入来设置 cookie 带入用户信息。
早先应甲方要求 web 网站关闭了,现在又要继续运行。于是就把 web 服务启动了,然后发现应用里积分商城还是进不去,然后就出事了。。。。。。
然后就开始找原因呗,在经过了几个然后之后,找到个前年写的钉钉文档里记录了当初为了应用加固做的操作,改了源码把 js,dom 什么的全禁了。
恢复了祖传代码,还有点问题:启动应用后,首次进入积分商城还是没有读到 cookie,退出页面重进就好了。一番折腾想到是加载顺序的问题:webview 里先加载了页面,页面加载后再注入 js,这导致页面拿 cookie 的时候 js 还没注入完成。cookie 是可以缓存的,所以退出页面后第二次进入会拿到第一次加载后注入的 cookie。
自然而然想到了通过调整顺序来解决---先添加 cookie,再请求 url。看到有个专门处理 cookie 的第三方 @react-native-oh-tpl/cookies,就直接拿来试试。依赖添加过程略过不表,参考
https://gitee.com/react-native-oh-library/usage-docs/blob/master/zh-cn/react-native-cookies-cookies.md#https://gitee.com/link?target=https%3A%2F%2Fgithub.com%2Freact-native-oh-library%2Freact-native-cookies%2Freleases。
直接使用 Release 里最新的 6.2.1-0.0.8 版本。页面逻辑也很简单
import CookieManager from '@react-native-oh-tpl/cookies';export interface Cookie { name: string; value: string; path?: string; domain?: string; version?: string; expires?: string; secure?: boolean; httpOnly?: boolean;}export interface Cookies { [key: string]: Cookie;}function PageABC({navigation, route}): JSX.Element { const [loading, setLoading] = useState(true); const [url, setUrl] = useState('我是url'); const expire = new Date( new Date().getTime() + 7 * 24 * 60 * 60, ).toUTCString(); const doInjectJS = async () => { await CookieManager.clearAll(); const curCookie1: Cookie = { name: 'xxxxxx', value: 'xxxxxx', domain: 'xxx.yyy.zzz', path: '/', expires: expire, }; let cookieResult1 = await CookieManager.set( url, curCookie1, true, ); const curCookie2: Cookie = { name: 'yyyyyy', value: 'yyyyyy', domain: 'xxx.yyy.zzz', path: '/', expires: expire, }; let cookieResult2 = await CookieManager.set( url, curCookie2, true, ); console.log(cookieResult1 + ' ' + cookieResult2); setLoading(false); }; /** * 模拟componentDidMount,即只运行一次该函数 */ useEffect(() => { doInjectJS(); return () => { }; }, []); /** * 模拟componentDidUpdate,所有 state 值其中任意一个值变化了都会触发该函数 */ useEffect(() => { }); /** * 这个 effect 会在标签页获得焦点时运行 */ useFocusEffect( React.useCallback(() => { }, []), ); return ( <View style={styles.bg}> <StatusBar barStyle={'default'} /> {!loading && ( <WebView bounces={false} style={{flex: 1}} source={{uri: url}} scalesPageToFit={true} startInLoadingState={true} // injectedJavaScript={injectJS} javaScriptEnabled={true} domStorageEnabled={true} useWebKit={true} onError={event => { console.log( '收到webview onError = ' + JSON.stringify(event.nativeEvent), ); }} onLoadEnd={event => { console.log( '收到webview onLoadEnd = ' + JSON.stringify(event.nativeEvent), ); }} onMessage={event => { console.log( '收到webview onMessage = ' + JSON.stringify(event.nativeEvent), ); }} /> )} {loading && ( <View style={styles.loadingBg}> <ActivityIndicator size="large" /> </View> )} </View> );}
复制代码
目前发现的问题有:应用跳转的积分商城页面域名只能设置当前域名,不能将 domain 设置成父域名,比如当前域名是 xxx.yyy.zzz,如果设置 domain 是.yyy.zzz 就会设置失败,感觉可能是服务端跨域设置有问题?挺奇怪的。要不是做了一把 clearAll()还发现不了。再议,再议。。。。。。
以上就是 @react-native-oh-tpl/cookies 设置页面 cookie 的方式。
===========我是新时代与旧时代的分隔线=====================
项目的鸿蒙 RN 版本是照着旧版 app 逻辑重新开发的,目前线上 android/ios 还是使用的旧版 RN 打包的版本。风烛残年的 android/ios 旧版已成传奇,那本当初开发用的旧笔记本专门供着这些个神仙工程。小尝试了下,拉取依赖都卡住了,用了个投机取巧的方式来应付:先去一个积分商城域名下的空页面,同时注入 js,等个 1 秒钟再跳转到积分商城首页。这种方式在鸿蒙版本上也试了下,也可行。当然还是有小概率会遇到读取不到 cookie 的情况,我承认这里面有赌的成分。
大概是这么个逻辑
let documentJs = '一段设置cookie的js实现,存在一些变量字符需要替换';function pageABC({navigation, route}): JSX.Element { const [loading, setLoading] = useState(true); const [injectJS, setInjectJS] = useState<string | null>(null); const [url, setUrl] = useState('空白页面url'); // 这个重试不一定需要,测试发现老项目有存在第一次替换失败的情况,但打印global.XXX又是有值的,这里就用了多次尝试的方式来处理 const doInjectJS = async () => { let retryCnt = 10; // 重试次数 while (retryCnt > 0) { if (global.userid) { documentJs = documentJs.replace('变量', global.userid); } if (documentJs.indexOf('变量') == -1) { retryCnt = 0; setInjectJS(documentJs); } else { await new Promise(resolve => setTimeout(resolve, 100)); // 等待100ms重试 retryCnt--; if (retryCnt == 0) { xnToast('积分商城加载失败,请尝试重新进入!'); setInjectJS(documentJs); } } } }; useEffect(() => { if (injectJS) { // 等1秒去真实url setTimeout(() => { setUrl('真实页面url'); setLoading(false); }, 1000); } }, [injectJS]); // console.log('render里打log,仅供调试') moment().format('YYYYMMDDHHmmss') return ( <View style={styles.bg}> <StatusBar barStyle={'default'} /> {injectJS && ( <WebView bounces={false} style={{flex: 1}} source={{uri: url}} scalesPageToFit={true} startInLoadingState={true} injectedJavaScript={injectJS} javaScriptEnabled={true} domStorageEnabled={true} useWebKit={true} onError={event => { console.log( '收到webview onError = ' + JSON.stringify(event.nativeEvent), ); }} onLoadEnd={event => { console.log( '收到webview onLoadEnd = ' + JSON.stringify(event.nativeEvent), ); }} onMessage={event => { console.log( '收到webview onMessage = ' + JSON.stringify(event.nativeEvent), ); }} /> )} {loading && ( <View style={styles.loadingBg}> <ActivityIndicator size="large" /> </View> )} </View> );}
复制代码
阴招毕竟是阴招,能走正常路数还是正常路数解决,除非伺候祖传代码。。。。。。
不经常在线,有问题可在微信公众号或者掘金社区私信留言
更多内容可关注我的公众号悬空八只脚
作者:悬空八只脚
链接:https://juejin.cn/post/7481533769053716491
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
评论