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,就直接拿来试试。依赖添加过程略过不表,参考
直接使用Release里最新的6.2.1-0.0.8版本。页面逻辑也很简单
typescript
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的情况,我承认这里面有赌的成分。
大概是这么个逻辑
typescript
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>
);
}
阴招毕竟是阴招,能走正常路数还是正常路数解决,除非伺候祖传代码。。。。。。
不经常在线,有问题可在微信公众号或者掘金社区私信留言
更多内容可关注
我的公众号悬空八只脚
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。