开源鸿蒙-基于React搭建GitCode口袋工具-2
参考博主【不羁的木木】做的笔记,顺便把自己看不懂的地方梳理,写一篇博客。下面为博主链接:【开源鸿蒙跨平台开发学习笔记】Day04:React Native 开发 HarmonyOS-GitCode口袋工具开发-2-CSDN博客。
·
前言
参考博主【不羁的木木】做的笔记,顺便把自己看不懂的地方梳理,写一篇博客。下面为博主链接:
一、踩坑
1.1 未加载Star的仓库
如果调用了已经starred的仓库的列表的接口"",但是列表却没显示出来,可能有以下两个原因。
https://api.gitcode.com/api/v5/users/:username/starred
1.你从未Starred过,也就不会显示有Star显示出来。所以这个时候你需要去GitCode的官网Star几个项目。
2.运行项目出现模拟器里面报错的情况,这个是因为React的代码里面有错,修改正确重新编译,再粘贴编译产生出来的文件即可。


二、编写React端的鸿蒙代码
2.1 修改代码
1.修改src/api目录下的client.tsx

import axios from 'axios';
// 默认令牌(开发调试用)
const DEFAULT_TOKEN = '你的GitCode令牌';
let privateToken = DEFAULT_TOKEN;
// 设置令牌的函数
export function setPrivateToken(token?: string) {
if (token) {
privateToken = token;
}
}
// 创建 axios 实例
export const http = axios.create({
baseURL: 'https://api.gitcode.com/api/v5/',
timeout: 10000,
});
// 请求拦截器 - 自动添加认证头
http.interceptors.request.use(config => {
const headers = config.headers ?? {};
headers['private-token'] = privateToken; // 添加认证令牌
config.headers = headers;
return config;
});
// 响应拦截器
http.interceptors.response.use(
res => res, // 直接返回成功响应
err => Promise.reject(err), // 传递错误
);
// 错误信息格式化函数
export function getErrorMessage(error: unknown): string {
if (axios.isAxiosError(error)) {
const status = error.response?.status;
const data = error.response?.data as any;
const msg = typeof data === 'string'
? data
: data?.message || data?.error || error.message;
return status ? `${status} ${msg}` : msg;
}
const e = error as any;
return String(e?.message || e);
}
2.修改src/api目录下的user.tsx

import {http} from './client';
import {UserProfile} from '../types/user';
// 支持查询指定用户或使用默认用户
export async function fetchUserProfile(username: string): Promise<UserProfile> {
const res = await http.get<UserProfile>(`users/${encodeURIComponent(username)}`);
return res.data;
}
export async function fetchStarred(username: string): Promise<any[]> {
const res = await http.get<any[]>(`users/${username}/starred`);
return res.data;
}
3.修改src/screens目录下的ExploreScreen.tsx(注意:这里的Deng666为我在GitCode的昵称,可以改成你自己的。)
Promise.all([fetchUserProfile('Deng666'), fetchStarred('Deng666')])

import React, {useEffect, useState} from 'react';
import {
View,
Text,
StyleSheet,
Image,
ActivityIndicator,
ScrollView,
Pressable,
Linking,
} from 'react-native';
import {fetchUserProfile, fetchStarred} from '../api';
import {UserProfile} from '../types/user';
import {getErrorMessage} from '../api/client';
// 已经是 ExploreScreen 和默认导出
export default function ExploreScreen(): JSX.Element {
const [data, setData] = useState<UserProfile | null>(null);
const [loading, setLoading] = useState<boolean>(false);
const [error, setError] = useState<string>('');
const [starred, setStarred] = useState<any[]>([]);
useEffect(() => {
let mounted = true;
setLoading(true);
setError('');
Promise.all([fetchUserProfile('Deng666'), fetchStarred('Deng666')])
.then(([d, s]) => {
if (!mounted) {
return;
}
setData(d);
setStarred(Array.isArray(s) ? s : []);
})
.catch(e => {
if (!mounted) {
return;
}
setError(getErrorMessage(e));
})
.finally(() => {
if (!mounted) {
return;
}
setLoading(false);
});
return () => {
mounted = false;
};
}, []);
// 安全的打开链接函数
const safeOpenURL = (url: string | undefined) => {
if (url && typeof url === 'string' && url.trim() !== '') {
Linking.openURL(url);
} else {
console.warn('无效的 URL:', url);
}
};
if (loading) {
return (
<View style={styles.center}>
<ActivityIndicator />
<Text style={styles.loadingText}>加载中</Text>
</View>
);
}
if (error) {
return (
<View style={styles.center}>
<Text style={styles.errorText}>请求失败:{error}</Text>
</View>
);
}
if (!data) {
return (
<View style={styles.center}>
<Text style={styles.errorText}>暂无数据</Text>
</View>
);
}
return (
<ScrollView contentContainerStyle={styles.scrollContent}>
<Image source={{uri: data.avatar_url}} style={styles.avatar} />
<Text style={styles.title}>{data.name || data.login}</Text>
<Text style={styles.subtitle}>类型:{data.type}</Text>
<Text style={styles.subtitle}>
粉丝:{data.followers},关注:{data.following}
</Text>
{Boolean(data.bio) && <Text style={styles.bio}>{data.bio}</Text>}
<Pressable
onPress={() => safeOpenURL(data.html_url)}
style={styles.linkButton}>
<Text style={styles.linkText}>打开主页</Text>
</Pressable>
<View style={styles.listHeader}>
<Text style={styles.listHeaderText}>已 Star 的仓库</Text>
</View>
{starred.map((item, idx) => {
const name =
item?.name || item?.path || item?.project_name || '未知仓库';
const desc = item?.description || '';
const link = item?.html_url || item?.web_url || item?.url || '';
return (
<View key={`${name}-${idx}`} style={styles.repoCard}>
<Text style={styles.repoName}>{name}</Text>
{!!desc && <Text style={styles.repoDesc}>{desc}</Text>}
{!!link && (
<Pressable
onPress={() => safeOpenURL(link)}
style={styles.repoLinkBtn}>
<Text style={styles.repoLinkText}>访问仓库</Text>
</Pressable>
)}
</View>
);
})}
</ScrollView>
);
}
const styles = StyleSheet.create({
center: {flex: 1, alignItems: 'center', justifyContent: 'center'},
loadingText: {marginTop: 8, fontSize: 14, color: '#666'},
errorText: {fontSize: 14, color: '#d00'},
scrollContent: {alignItems: 'center', paddingVertical: 24},
avatar: {width: 120, height: 120, borderRadius: 60, backgroundColor: '#eee'},
title: {marginTop: 16, fontSize: 24, fontWeight: '700'},
subtitle: {marginTop: 8, fontSize: 16, color: '#666'},
bio: {
marginTop: 12,
fontSize: 14,
color: '#333',
paddingHorizontal: 24,
textAlign: 'center',
},
linkButton: {
marginTop: 16,
paddingHorizontal: 16,
paddingVertical: 10,
borderRadius: 6,
backgroundColor: '#007aff',
},
linkText: {color: '#fff', fontSize: 14, fontWeight: '600'},
listHeader: {width: '100%', paddingHorizontal: 24, paddingTop: 24},
listHeaderText: {fontSize: 18, fontWeight: '600'},
repoCard: {
width: '92%',
marginTop: 12,
padding: 12,
borderRadius: 8,
backgroundColor: '#f7f7f7',
},
repoName: {fontSize: 16, fontWeight: '600'},
repoDesc: {marginTop: 6, fontSize: 14, color: '#555'},
repoLinkBtn: {
marginTop: 10,
alignSelf: 'flex-start',
paddingHorizontal: 12,
paddingVertical: 8,
borderRadius: 6,
backgroundColor: '#34c759',
},
repoLinkText: {color: '#fff', fontSize: 14, fontWeight: '600'},
});
2.2 执行编译命令
执行编译的命令'npm run dev",将生成的"\AwesomeProject\harmony\entry\src\main\resources\rawfile"目录下的"bundle.harmony.js"拷贝到鸿蒙项目里的"rawfile"目录下。最后,编译运行项目,可以看到,项目已经显示出来我们Starred过的项目。(如果没显示,可能是因为你从未Starred过,可以去GitCode官网给几个项目点Star~)




更多推荐



所有评论(0)