Skip to content

React Native ViewPropTypes 迁移指南

问题描述

当使用 React Native 0.68 及以上版本时,你可能会在控制台看到以下警告:

ViewPropTypes will be removed from React Native. Migrate to ViewPropTypes exported from 'deprecated-react-native-prop-types'

这个警告表明 React Native 正在废弃 PropTypes 系统,即使你没有直接在代码中使用 ViewPropTypes,但某些第三方库可能仍在使用了它。

解决方案概览

有几种方法可以解决这个问题:

  1. 短期解决方案:安装兼容包并修改 node_modules(不推荐)
  2. 中期解决方案:使用 patch-package 创建永久补丁
  3. 长期解决方案:更新或修复依赖库
  4. 临时解决方案:忽略警告

解决方案详解

方案一:安装兼容包并修改(不推荐)

不推荐

直接修改 node_modules 中的文件不是最佳实践,因为这些更改会在重新安装依赖时丢失。

  1. 安装兼容包:
bash
npm install deprecated-react-native-prop-types
# 或
yarn add deprecated-react-native-prop-types
  1. 修改 node_modules/react-native/index.js 文件,找到以下代码段:
javascript
// Deprecated Prop Types
get ColorPropType(): $FlowFixMe {
  invariant(false, "...");
},
get EdgeInsetsPropType(): $FlowFixMe {
  invariant(false, "...");
},
get PointPropType(): $FlowFixMe {
  invariant(false, "...");
},
get ViewPropTypes(): $FlowFixMe {
  invariant(false, "...");
},
  1. 替换为:
javascript
// Deprecated Prop Types
get ColorPropType(): $FlowFixMe {
  return require("deprecated-react-native-prop-types").ColorPropType;
},
get EdgeInsetsPropType(): $FlowFixMe {
  return require("deprecated-react-native-prop-types").EdgeInsetsPropType;
},
get PointPropType(): $FlowFixMe {
  return require("deprecated-react-native-prop-types").PointPropType;
},
get ViewPropTypes(): $FlowFixMe {
  return require("deprecated-react-native-prop-types").ViewPropTypes;
},

方案二:使用 patch-package(推荐)

这是更可持续的解决方案,可以确保修改在重新安装依赖后仍然有效。

  1. 安装所需包:
bash
npm install --save-dev patch-package deprecated-react-native-prop-types
  1. 按照方案一的步骤修改 node_modules/react-native/index.js

  2. 创建补丁:

bash
npx patch-package react-native

这会创建一个 patches 文件夹,其中包含对 react-native 包的修改。每次安装依赖后,patch-package 会自动应用这些补丁。

  1. 在 package.json 中添加 postinstall 脚本:
json
"scripts": {
  "postinstall": "patch-package"
}

方案三:修复第三方库

如果警告来自特定的第三方库,你应该直接修复这些库或等待库维护者更新。

  1. 找出是哪个库使用了 ViewPropTypes:
bash
grep -r "ViewPropTypes" node_modules/
  1. 对于每个使用 ViewPropTypes 的库,找到相关文件并将导入从:
javascript
import { ViewPropTypes } from 'react-native';

改为:

javascript
import { ViewPropTypes } from 'deprecated-react-native-prop-types';
  1. 使用 patch-package 为这些库创建补丁:
bash
npx patch-package package-name

方案四:使用模块解析器(高级)

对于更复杂的项目,可以使用 babel-plugin-module-resolver 来重定向导入。

  1. 安装必要的包:
bash
npm install --save-dev babel-plugin-module-resolver deprecated-react-native-prop-types
  1. 创建 resolver/react-native/index.js
javascript
import * as StandardModule from "react-native";

const deprecatedProps = {
  ImagePropTypes: require("deprecated-react-native-prop-types/DeprecatedImagePropType"),
  TextPropTypes: require("deprecated-react-native-prop-types/DeprecatedTextPropTypes"),
  ViewPropTypes: require("deprecated-react-native-prop-types/DeprecatedViewPropTypes"),
  ColorPropType: require("deprecated-react-native-prop-types/DeprecatedColorPropType"),
  EdgeInsetsPropType: require("deprecated-react-native-prop-types/DeprecatedEdgeInsetsPropType"),
  PointPropType: require("deprecated-react-native-prop-types/DeprecatedPointPropType"),
};

// 创建代理对象处理导入重定向
const objProx = new Proxy(StandardModule, {
  get(_, prop) {
    if (prop in deprecatedProps) {
      return deprecatedProps[prop];
    }
    return Reflect.get(...arguments);
  },
});

module.exports = objProx;
  1. 配置 babel.config.js:
javascript
var path = require('path');

module.exports = {
  presets: ['module:metro-react-native-babel-preset'],
  plugins: [
    ["module-resolver", {
      "root": ["."],
      resolvePath(sourcePath, currentFile, opts) {
        if (
          sourcePath === 'react-native' &&
          !currentFile.includes('node_modules/react-native/') &&
          !currentFile.includes('resolver/react-native/')
        ) {
          return path.resolve(__dirname, 'resolver/react-native');
        }
        return undefined;
      }
    }],
  ],
};

方案五:暂时忽略警告

如果你需要快速解决问题而不想修改代码,可以暂时忽略这些警告:

javascript
import { LogBox } from "react-native";

if (__DEV__) {
  const ignoreWarns = [
    "ViewPropTypes will be removed from React Native",
    "exported from 'deprecated-react-native-prop-types'.",
  ];

  const warn = console.warn;
  console.warn = (...arg) => {
    for (const warning of ignoreWarns) {
      if (arg[0].startsWith(warning)) {
        return;
      }
    }
    warn(...arg);
  };

  LogBox.ignoreLogs(ignoreWarns);
}

最佳实践建议

  1. 优先使用 TypeScript:React 团队推荐迁移到 TypeScript 作为类型检查解决方案
  2. 定期更新依赖:保持第三方库的最新版本,以避免这类兼容性问题
  3. 贡献修复:如果你修复了第三方库的问题,考虑向原项目提交 PR 帮助社区
  4. 使用 patch-package:这是管理 node_modules 修改的最可靠方法

结论

ViewPropTypes 警告是 React Native 废弃 PropTypes 系统的结果。虽然有多种解决方法,但推荐使用 patch-package 创建可持续的补丁,或者更好的是,迁移到 TypeScript 并更新所有依赖到最新版本。

长期来看,随着库维护者更新他们的代码库,这个问题将自然解决。在此期间,上述解决方案可以帮助你保持项目的正常运行。