已开启
fix: 修改nativewind三方库AI文档质量扫描整改 #19
fix: 修改nativewind三方库AI文档质量扫描整改 #19
已开启
fanwangah创建于 8月3日
5 个文件变更+178-118
MREADME.md+4-48
@@ -40,19 +40,6 @@ npx tailwindcss init
40 40 
41### **在你的 tailwind.config.js 文件中添加所有组件文件的路径。**41### **在你的 tailwind.config.js 文件中添加所有组件文件的路径。**
42 42 
43-- V2.0.11
44- 
45-```diff
46-module.exports = {
47-- content: [],
48-+ content: ["./App.{js,jsx,ts,tsx}", "./screens/**/*.{js,jsx,ts,tsx}"],
49- theme: {
50- extend: {},
51- },
52- plugins: [],
53-}
54-```
55- 
56- V4.1.2443- V4.1.24
57 44 
58```diff45```diff
@@ -69,15 +56,6 @@ module.exports = {
69 56 
70### **修改你的 babel.config.js**57### **修改你的 babel.config.js**
71 58 
72-- V2.0.11
73- 
74-```diff
75-module.exports = {
76-- plugins: [],
77-+ plugins: ["@react-native-oh-tpl/nativewind/babel"],
78-};
79-```
80- 
81- V4.1.2459- V4.1.24
82 60 
83```diff61```diff
@@ -124,28 +102,6 @@ const config = getDefaultConfig(__dirname)
124 102 
125> [!WARNING] 使用时 import 的库名不变。103> [!WARNING] 使用时 import 的库名不变。
126 104 
127-- V2.0.11
128- 
129-```jsx
130-import React from 'react';
131-import { Text, View } from 'react-native';
132-import { styled } from 'nativewind';
133- 
134-const StyledView = styled(View)
135-const StyledText = styled(Text)
136-const NativewindDemo = () => {
137- return (
138- <StyledView className="flex-1 items-center justify-center">
139- <StyledText className="font-bold">
140- Hello,World.
141- </StyledText>
142- </StyledView>
143- )
144-}
145- 
146-export default NativewindDemo
147-```
148- 
149- V4.1.24<sup>+</sup>105- V4.1.24<sup>+</sup>
150 106 
151```jsx107```jsx
@@ -175,16 +131,16 @@ export default function App() {
175 131 
176| Name | Description | Type | Required | Platform | HarmonyOS Support |132| Name | Description | Type | Required | Platform | HarmonyOS Support |
177| -------------------------------- | ------------------------------------------------------------ | --------- | -------- | -------- | ----------------- |133| -------------------------------- | ------------------------------------------------------------ | --------- | -------- | -------- | ----------------- |
178-| withNativeWind<sup>4.1.24+</sup> | `withNativeWind` 是一个高阶组件,用于更新你的 Metro 配置文件,以提供 NativeWind 框架支持。 | component | no | All | yes |134+| withNativeWind | `withNativeWind` 是一个高阶组件,用于更新你的 Metro 配置文件,以提供 NativeWind 框架支持。 | component | no | All | yes |
179-| remapProps<sup>4.1.24+</sup> | NativeWind 提供了 `remapProps` 工具函数,简化对带有多个 `style` 属性的第三方组件的开发操作。 | component | no | All | yes |135+| remapProps | NativeWind 提供了 `remapProps` 工具函数,简化对带有多个 `style` 属性的第三方组件的开发操作。 | component | no | All | yes |
180-| cssInterop<sup>4.1.24+</sup> | 该函数会给组件打上标记,这样组件渲染时,运行时就能识别并将组件的 `className` 字符串转换为样式。 | component | no | All | yes |136+| cssInterop | 该函数会给组件打上标记,这样组件渲染时,运行时就能识别并将组件的 `className` 字符串转换为样式。 | component | no | All | yes |
181 137 
182### API138### API
183 139 
184| Name | Description | Type | Required | Platform | HarmonyOS Support |140| Name | Description | Type | Required | Platform | HarmonyOS Support |
185| ----------------------------------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | -------- | -------- | ----------------- |141| ----------------------------------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | -------- | -------- | ----------------- |
186| useColorScheme() | 用于获取设备的配色方案信息。 | () =>{colorScheme,setColorScheme} | no | All | yes |142| useColorScheme() | 用于获取设备的配色方案信息。 | () =>{colorScheme,setColorScheme} | no | All | yes |
187-| var<sup>4.1.24+</sup> | `vars` 是一个函数,接收一组 CSS 变量键值对象作为参数,并返回一个可在 React Native 组件中使用的样式对象。 | function | no | All | yes |143+| vars | `vars` 是一个函数,接收一组 CSS 变量键值对象作为参数,并返回一个可在 React Native 组件中使用的样式对象。 | function | no | All | yes |
188 144 
189## 遗留问题145## 遗留问题
190 146 
@@ -40,19 +40,6 @@ npx tailwindcss init
40 40 
41### **Add the file paths of all components to your `tailwind.config.js` file**41### **Add the file paths of all components to your `tailwind.config.js` file**
42 42 
43-- V2.0.11
44- 
45-```diff
46-module.exports = {
47-- content: [],
48-+ content: ["./App.{js,jsx,ts,tsx}", "./screens/**/*.{js,jsx,ts,tsx}"],
49- theme: {
50- extend: {},
51- },
52- plugins: [],
53-}
54-```
55- 
56- V4.1.2443- V4.1.24
57 44 
58```diff45```diff
@@ -69,15 +56,6 @@ module.exports = {
69 56 
70### **Modify your `babel.config.js`**57### **Modify your `babel.config.js`**
71 58 
72-- V2.0.11
73- 
74-```diff
75-module.exports = {
76-- plugins: [],
77-+ plugins: ["@react-native-oh-tpl/nativewind/babel"],
78-};
79-```
80- 
81- V4.1.2459- V4.1.24
82 60 
83```diff61```diff
@@ -124,28 +102,6 @@ The following code shows the basic use scenario of the repository:
124 102 
125> [!WARNING] The name of the imported repository remains unchanged.103> [!WARNING] The name of the imported repository remains unchanged.
126 104 
127-- V2.0.11
128- 
129-```jsx
130-import React from 'react';
131-import { Text, View } from 'react-native';
132-import { styled } from 'nativewind';
133- 
134-const StyledView = styled(View)
135-const StyledText = styled(Text)
136-const NativewindDemo = () => {
137- return (
138- <StyledView className="flex-1 items-center justify-center">
139- <StyledText className="font-bold">
140- Hello,World.
141- </StyledText>
142- </StyledView>
143- )
144-}
145- 
146-export default NativewindDemo
147-```
148- 
149- V4.1.24<sup>+</sup>105- V4.1.24<sup>+</sup>
150 106 
151```jsx107```jsx
@@ -175,16 +131,16 @@ export default function App() {
175 131 
176| Name | Description | Type | Required | Platform | HarmonyOS Support |132| Name | Description | Type | Required | Platform | HarmonyOS Support |
177| -------------------------------- | ------------------------------------------------------------ | --------- | -------- | -------- | ----------------- |133| -------------------------------- | ------------------------------------------------------------ | --------- | -------- | -------- | ----------------- |
178-| withNativeWind<sup>4.1.24+</sup> | withNativeWind is a higher order component that updates your Metro configuration to support NativeWind | component | no | All | yes |134+| withNativeWind | withNativeWind is a higher order component that updates your Metro configuration to support NativeWind | component | no | All | yes |
179-| remapProps<sup>4.1.24+</sup> | Nativewind provides the remapProps utility to simplify working with third-party components with multiple "style" props. | component | no | All | yes |135+| remapProps | Nativewind provides the remapProps utility to simplify working with third-party components with multiple "style" props. | component | no | All | yes |
180-| cssInterop<sup>4.1.24+</sup> | This function "tags" components so that when its rendered, the runtime will know to resolve component className strings into styles. | component | no | All | yes |136+| cssInterop | This function "tags" components so that when its rendered, the runtime will know to resolve component className strings into styles. | component | no | All | yes |
181 137 
182### API138### API
183 139 
184| Name | Description | Type | Required | Platform | HarmonyOS Support |140| Name | Description | Type | Required | Platform | HarmonyOS Support |
185| ----------------------------------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | -------- | -------- | ----------------- |141| ----------------------------------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | -------- | -------- | ----------------- |
186| useColorScheme() | provides access to the devices color scheme. | () =>{colorScheme,setColorScheme} | no | All | yes |142| useColorScheme() | provides access to the devices color scheme. | () =>{colorScheme,setColorScheme} | no | All | yes |
187-| var<sup>4.1.24+</sup> | vars is a function that takes a dictionary of CSS variables and returns a style object that can be used in React Native components. | function | no | All | yes |143+| vars | vars is a function that takes a dictionary of CSS variables and returns a style object that can be used in React Native components. | function | no | All | yes |
188 144 
189## Known Issues145## Known Issues
190 146 
@@ -13,13 +13,6 @@
13 "deliveryWithInstall": true,13 "deliveryWithInstall": true,
14 "installationFree": false,14 "installationFree": false,
15 "pages": "$profile:main_pages",15 "pages": "$profile:main_pages",
cpf-manager
cpf-managercpf-manager8月3日

【AI-Review】【严重】【基础代码问题】【代码逻辑错误】移除 ohos.permission.INTERNET 导致 Metro 开发模式无法加载 JS bundle

● 问题: example/harmony/entry/src/main/module.json5 本 PR 删除了 requestPermissions 中的 ohos.permission.INTERNET 权限。但 example/harmony/entry/src/main/ets/pages/Index.ets 第101行 jsBundleProvidernew MetroJSBundleProvider() 作为首个 JS bundle 提供者,该提供者通过 HTTP(localhost:8081)从 Metro 开发服务器拉取 JS bundle。example/package.json 的 start 脚本 hdc rport tcp:8081 tcp:8081 && react-native start 即为该模式准备(hdc 反向端口转发 + Metro 服务)。HarmonyOS 应用访问网络(包括 localhost TCP 连接)需要 ohos.permission.INTERNET 权限。

● 影响: 严重。移除该权限后,MetroJSBundleProvider 无法建立到 Metro 服务器的网络连接,npm start 开发模式(带热重载/Fast Refresh)失效。开发者只能依赖 npm run dev/npm run prod 预打包的 bundle(FileJSBundleProvider/ResourceJSBundleProvider)才能运行应用,丧失开发期的实时调试能力。

● 建议: 恢复 ohos.permission.INTERNET 权限声明:

"requestPermissions": [
  {
    "name": "ohos.permission.INTERNET"
  },
],
likedislike
16- // below property is supported from 5.0.0 - it is needed by bundleManager.canOpenLink to check if the app can open some url
17- // "querySchemes": ["maps", "http", "https", "customDomain"],
18- "requestPermissions": [
19- {
20- "name": "ohos.permission.INTERNET"
21- },
22- ],
23 "metadata": [16 "metadata": [
24 {17 {
25 "name": "OPTLazyForEach",18 "name": "OPTLazyForEach",
@@ -0,0 +1,3 @@
1+{
2+ "presets": ["@react-native-ohos/nativewind/babel"]
cpf-manager
cpf-managercpf-manager8月3日

【AI-Review】【建议】【软件设计】【冗余重复代码】.babelrc 与 babel.config.js 配置重复

● 问题: example/src/.babelrc(本 PR 新增)配置 {"presets": ["@react-native-ohos/nativewind/babel"]},而 example/babel.config.js 第2行已配置 presets: ['module:@react-native/babel-preset', '@react-native-ohos/nativewind/babel'],nativewind babel preset 已包含在内。Babel 解析 example/src/ 下的文件时会同时合并 babel.config.js(项目级)与 .babelrc(目录级)配置,导致 nativewind preset 被重复应用。

● 影响: 建议。nativewind babel 插件(packages/react-native-css-interop/src/babel-plugin.ts)将 React.createElement 替换为 createInteropElement,二次应用时首轮已替换完毕、第二轮无匹配项为空操作,不会导致运行时错误,但造成不必要的重复 AST 遍历,且两处配置并存易在后续维护中产生混淆(如修改 babel.config.js 时忽略 .babelrc 仍在生效)。

● 建议: 删除 example/src/.babelrc,统一由 example/babel.config.js 管理构建配置。

likedislike
3+}
@@ -1,18 +1,170 @@
1-/*1+import "../../../global.css"
cpf-manager
cpf-managercpf-manager8月3日

【AI-Review】【致命】【基础代码问题】【代码逻辑错误】global.css 导入路径错误导致构建失败

● 问题: example/src/index.tsx 第1行 import "../../../global.css" 的相对路径解析错误。该文件位于 example/src/index.tsx../../../global.cssexample/src/ 向上解析三级到达仓库根目录的父目录,该位置不存在 global.css 文件。仓库中唯一的 global.css 位于 example/global.css(与 example/metro.config.js 中 withNativeWind(config2, { input: './global.css' }) 的 input 配置一致)。base 版本(SHA 01d02e57)的导入为 import "../global.css",能正确解析到 example/global.css,本 PR 将其改为 ../../../global.css 后路径失效。

● 影响: 致命。Metro 解析器(packages/react-native-css-interop/src/metro/index.ts 的 resolveRequest)先调用原始 resolver 解析导入路径,再比对 options.input。由于 ../../../global.css 不存在,Metro 抛出 Module not found 错误,导致 example 应用在 npm run dev(bundle-harmony 打包)和 npm start(Metro 开发模式)下均无法构建,整个示例应用无法启动。

● 建议: 将导入路径改回 ../global.css

import "../global.css"
likedislike
2- * Copyright (c) 2025 Huawei Device Co., Ltd. All rights reserved2+import { Text, View, ScrollView, Button, TextInput, TouchableOpacity, StyleSheet } from 'react-native';
3- * Use of this source code is governed by a MIT license that can be3+import { vars, useColorScheme, remapProps, cssInterop } from 'nativewind';
4- * found in the LICENSE file.4+import { Tester, TestCase, TestSuite } from '@rnoh/testerino';
5- */
6 5 
7-import "../global.css"
8-import { Text, View } from "react-native";
9-
10export default function App() {6export default function App() {
11- return (7+ 
12- <View className="flex-1 items-center justify-center bg-white">8+ const { colorScheme, setColorScheme } = useColorScheme();
13- <Text className="text-xl font-bold text-blue-500">9+ const theme = vars({
14- Welcome to Nativewind!10+ "--theme-fg": "green",
15- </Text>11+ });
16- </View>12+ type ThirdPartyButtonProps = {
13+ buttonStyle?: any;
14+ labelStyle?: any;
15+ children?: React.ReactNode;
16+ [key: string]: any;
17+ };
18+ const ThirdPartyButton = ({ buttonStyle, labelStyle, children, ...props }: ThirdPartyButtonProps) => (
19+ <TouchableOpacity style={buttonStyle} {...props}>
20+ <Text style={labelStyle}>{children}</Text>
21+ </TouchableOpacity>
17 );22 );
18-}23+ const CustomizedButton = remapProps(ThirdPartyButton, {
24+ buttonClass: "buttonStyle",
25+ labelClass: "labelStyle",
26+ });
27+ const MyInput = (props) => <TextInput {...props} />;
28+ const OverridenTextInput = remapProps(MyInput, { className: "style" });
cpf-manager
cpf-managercpf-manager8月3日

【AI-Review】【严重】【基础代码问题】【代码逻辑错误】组件与 cssInterop 在 App 函数体内定义导致重渲染时状态丢失

● 问题: example/src/index.tsx 第18-28行将 ThirdPartyButtonCustomizedButton = remapProps(ThirdPartyButton, ...)MyInputOverridenTextInput = remapProps(MyInput, ...) 以及第30、45行的 cssInterop(TextInput, ...)cssInterop(Tester, ...) 全部定义在 App 函数体内部。每次 App 渲染都会创建新的函数引用和新的 HOC 实例。useColorScheme()(packages/react-native-css-interop/src/runtime/native/api.ts 第101行 useColorScheme)返回的 setColorScheme 被绑定到"切换主题"按钮(onPress 中调用 setColorScheme(colorScheme === 'light' ? 'dark' : 'light'))。当用户点击该按钮时,setColorScheme 触发 App 重新渲染,所有内部定义的组件获得新的函数引用,React 协调器判定为不同组件类型并执行卸载-重新挂载。

● 影响: 严重。用户在 OverridenTextInput(第27行 MyInput 包装的 TextInput)中输入文本后,点击"切换主题"按钮,App 重渲染导致 OverridenTextInput 被卸载并重新挂载,输入内容丢失、键盘收起、焦点丢失。CustomizedButton 同理丢失按压状态。这破坏了示例应用的演示效果。

● 建议: 将组件定义、remapProps/cssInterop 调用移到模块作用域(App 函数外部):

// 模块作用域
const ThirdPartyButton = ({ buttonStyle, labelStyle, children, ...props }) => ( ... );
const CustomizedButton = remapProps(ThirdPartyButton, { buttonClass: "buttonStyle", labelClass: "labelStyle" });
const MyInput = (props) => <TextInput {...props} />;
const OverridenTextInput = remapProps(MyInput, { className: "style" });
cssInterop(TextInput, { className: { target: "style", nativeStyleToProp: { textAlign: true } }, placeholderClassName: { target: false, nativeStyleToProp: { color: "placeholderTextColor" } } });
cssInterop(Tester, { className: { target: "style", nativeStyleToProp: { textAlign: true } } });

export default function App() {
  const { colorScheme, setColorScheme } = useColorScheme();
  // ...
}
likedislike
29+ 
30+ cssInterop(TextInput, {
31+ className: {
32+ target: "style",
33+ nativeStyleToProp: {
34+ textAlign: true,
35+ },
36+ },
37+ placeholderClassName: {
38+ target: false,
39+ nativeStyleToProp: {
40+ color: "placeholderTextColor",
41+ },
42+ }
43+ });
44+ 
45+ cssInterop(Tester, {
46+ className: {
47+ target: "style",
48+ nativeStyleToProp: {
49+ textAlign: true,
50+ },
51+ }
52+ });
53+ return (
54+ <Tester className="flex-1 bg-black pt-20">
55+ <ScrollView>
56+ <Text className="text-4xl text-white font-bold">withNativeWind桥接</Text>
57+ <TestSuite name='hooks:withNativeWind()'>
58+ <TestCase itShould='withNativeWind()'>
59+ <View>
60+ <TextInput
61+ className="h-12 w-full p-2.5 border border-red-300 rounded-md
62+ text-base
63+ text-orange-700
64+ bg-red-500
65+ shadow
66+ "
67+ placeholderClassName="text-green-700"
68+ placeholder="placeholder"
69+ />
70+ </View>
71+ </TestCase>
72+ </TestSuite>
73+ 
74+ <Text className="text-4xl text-white font-bold">vars</Text>
75+ <TestSuite name='设置CSS 变量'>
76+ <View className="h-12"></View>
77+ <View style={vars({ '--brand-color': 'red' })}>
78+ <Text className="text-[--brand-color]" >
79+ Welcome to Nativewind!
80+ </Text>
81+ </View>
82+ <View className="h-12"></View>
83+ <View className="flex-1 justify-center items-center gap-10" style={theme}>
84+ <Text className="text-[--theme-fg]">Variables!!!</Text>
85+ </View>
86+ <View className="h-12"></View>
87+ </TestSuite>
88+ 
89+ <Text className="text-4xl text-white font-bold">useColorScheme</Text>
90+ <TestSuite name='hooks:useColorScheme()'>
91+ <TestCase tags={['C_API']} itShould='useColorScheme()'>
92+ <View style={{ height: 120, alignItems: 'center', justifyContent: 'center' }}>
93+ <View className='dark:bg-black w-60 h-8 rounded-md'>
94+ <Text className='dark:text-white leading-6 text-center' >{'light:白底黑字;dark:黑底白字'}</Text>
95+ </View>
96+ <View className='w-48 h-8 rounded-md'>
97+ <Text className='leading-6 text-center' >{colorScheme}</Text>
98+ </View>
99+ <Button
100+ title='点击切换主题'
101+ onPress={() => {
102+ setColorScheme(colorScheme === 'light' ? 'dark' : 'light')
103+ }}
104+ />
105+ </View>
106+ </TestCase>
107+ </TestSuite>
108+ <Text className="text-4xl text-white font-bold">remapProps</Text>
109+ <TestSuite name='hooks:remapProps()'>
110+ <TestCase itShould='remapProps()'>
111+ <View className="p-12">
112+ <CustomizedButton buttonClass="bg-blue-500 p-2" labelClass="text-white font-bold">
113+ 按钮
114+ </CustomizedButton>
115+ </View>
116+ <View className="px-12">
117+ <OverridenTextInput
118+ className="
119+ h-12
120+ w-full
121+ p-2
122+ border
123+ border-gray-300
124+ rounded-md
125+ text-base
126+ text-black
127+ bg-white
128+ shadow
129+ "
130+ placeholder="placeholder" keyboardType="numeric" />
131+ </View>
132+ <View className="h-12"></View>
133+ </TestCase>
134+ </TestSuite>
135+ <Text className="text-4xl text-white font-bold">cssInterop</Text>
136+ <TestSuite name='hooks:cssInterop()'>
137+ <TestCase itShould='cssInterop()'>
138+ <View className="p-12">
139+ <TextInput
140+ className="h-12 w-full p-2.5 border border-red-300 rounded-md
141+ text-base
142+ text-orange-700
143+ bg-white
144+ shadow
145+ "
146+ placeholderClassName="text-green-700"
147+ placeholder="placeholder"
148+ />
149+ </View>
150+ </TestCase>
151+ </TestSuite>
152+ </ScrollView>
153+ </Tester>
154+ );
155+}
156+ 
157+const styles = StyleSheet.create({
158+ button: {
159+ backgroundColor: "#10B981",
160+ paddingVertical: 12,
161+ paddingHorizontal: 24,
162+ borderRadius: 6,
163+ alignItems: "center",
164+ },
165+ buttonText: {
166+ color: "#ffffff",
167+ fontWeight: "600",
168+ fontSize: 16,
169+ },
170+});