检查字符串强制转换
'' value 模式(用于性能敏感代码)对 Symbol 和 Temporal.* 类型会抛出异常。参见 https://github.com/facebook/react/pull/22064。
本模块中的函数会抛出更易于理解和调试的异常,并带有清晰的错误信息来解释问题。(而不是在 value 对象的实现内部抛出令人困惑的异常)。
一、作用
二、检查属性字符串强制转换
export function checkAttributeStringCoercion(
value: mixed,
attributeName: string,
): void | string {
if (__DEV__) {
if (willCoercionThrow(value)) {
console.error(
'The provided `%s` attribute is an unsupported type %s.' +
' This value must be coerced to a string before using it here.',
attributeName,
typeName(value),
);
// throw (to help callers find troubleshooting comments)
// 抛出(帮助调用者找到故障排除注释)
return testStringCoercion(value);
}
}
}
三、检查键字符串强制转换
export function checkKeyStringCoercion(value: mixed): void | string {
if (__DEV__) {
if (willCoercionThrow(value)) {
console.error(
'The provided key is an unsupported type %s.' +
' This value must be coerced to a string before using it here.',
typeName(value),
);
// throw (to help callers find troubleshooting comments)
// 抛出(帮助调用者找到故障排除注释)
return testStringCoercion(value);
}
}
}
四、检查属性字符串强制转换
export function checkPropStringCoercion(
value: mixed,
propName: string,
): void | string {
if (__DEV__) {
if (willCoercionThrow(value)) {
console.error(
'The provided `%s` prop is an unsupported type %s.' +
' This value must be coerced to a string before using it here.',
propName,
typeName(value),
);
// throw (to help callers find troubleshooting comments)
// 抛出(帮助调用者找到故障排除注释)
return testStringCoercion(value);
}
}
}
五、检查选项字符串强制类型转换
export function checkOptionStringCoercion(
value: mixed,
propName: string,
): void | string {
if (__DEV__) {
if (willCoercionThrow(value)) {
console.error(
'The provided `%s` option is an unsupported type %s.' +
' This value must be coerced to a string before using it here.',
propName,
typeName(value),
);
// throw (to help callers find troubleshooting comments)
// 抛出(帮助调用者找到故障排除注释)
return testStringCoercion(value);
}
}
}
六、检查CSS属性字符串强制转换
export function checkCSSPropertyStringCoercion(
value: mixed,
propName: string,
): void | string {
if (__DEV__) {
if (willCoercionThrow(value)) {
console.error(
'The provided `%s` CSS property is an unsupported type %s.' +
' This value must be coerced to a string before using it here.',
propName,
typeName(value),
);
// throw (to help callers find troubleshooting comments)
// 抛出(帮助调用者找到故障排除注释)
return testStringCoercion(value);
}
}
}
七、检查HTML字符串强制转换
export function checkHtmlStringCoercion(value: mixed): void | string {
if (__DEV__) {
if (willCoercionThrow(value)) {
console.error(
'The provided HTML markup uses a value of unsupported type %s.' +
' This value must be coerced to a string before using it here.',
typeName(value),
);
// throw (to help callers find troubleshooting comments)
// 抛出(帮助调用者找到故障排除注释)
return testStringCoercion(value);
}
}
}
八、检查表单字段值字符串强制转换
export function checkFormFieldValueStringCoercion(value: mixed): void | string {
if (__DEV__) {
if (willCoercionThrow(value)) {
console.error(
'Form field values (value, checked, defaultValue, or defaultChecked props)' +
' must be strings, not %s.' +
' This value must be coerced to a string before using it here.',
typeName(value),
);
// throw (to help callers find troubleshooting comments)
// 抛出(帮助调用者找到故障排除注释)
return testStringCoercion(value);
}
}
}
九、检查表单字段值的字符串强制转换
export function checkFormFieldValueStringCoercion(value: mixed): void | string {
if (__DEV__) {
if (willCoercionThrow(value)) {
console.error(
'Form field values (value, checked, defaultValue, or defaultChecked props)' +
' must be strings, not %s.' +
' This value must be coerced to a string before using it here.',
typeName(value),
);
// throw (to help callers find troubleshooting comments)
// 抛出(帮助调用者找到故障排除注释)
return testStringCoercion(value);
}
}
}
十、工具
1. 类型名称
function typeName(value: mixed): string {
if (__DEV__) {
// toStringTag is needed for namespaced types like Temporal.Instant
// toStringTag 对于像 Temporal.Instant 这样的命名空间类型是必要的
const hasToStringTag = typeof Symbol === 'function' && Symbol.toStringTag;
const type =
(hasToStringTag && (value as any)[Symbol.toStringTag]) ||
(value as any).constructor.name ||
'Object';
return type;
}
}
2. 强制转换会抛出异常
function willCoercionThrow(value: mixed): boolean {
if (__DEV__) {
try {
testStringCoercion(value);
return false;
} catch (e) {
return true;
}
}
}
3. 测试字符串强制转换
function testStringCoercion(value: mixed) {
// If you ended up here by following an exception call stack, here's what's
// happened: you supplied an object or symbol value to React (as a prop, key,
// DOM attribute, CSS property, string ref, etc.) and when React tried to
// coerce it to a string using `'' + value`, an exception was thrown.
//
// 如果你是通过跟踪异常调用堆栈来到这里的,发生了以下情况:
// 你向 React 提供了一个对象或符号值(作为 prop、key、DOM 属性、CSS 属性、字符串 ref 等),
// 当 React 尝试使用 `'' + value` 将其强制转换为字符串时,抛出了异常。
//
// The most common types that will cause this exception are `Symbol` instances
// and Temporal objects like `Temporal.Instant`. But any object that has a
// `valueOf` or `[Symbol.toPrimitive]` method that throws will also cause this
// exception. (Library authors do this to prevent users from using built-in
// numeric operators like `+` or comparison operators like `>=` because custom
// methods are needed to perform accurate arithmetic or comparison.)
//
// 最常见会导致此异常的类型是 `Symbol` 实例和像 `Temporal.Instant` 这样的 Temporal 对象。
// 但任何具有会抛出异常的 `valueOf` 或 `[Symbol.toPrimitive]` 方法的对象也会导致此异常。
// (库作者这样做是为了防止用户使用内置的数字运算符如 `+` 或比较运算符如 `>=`,因为执行精确的算术
// 或比较需要自定义方法。)
//
// To fix the problem, coerce this object or symbol value to a string before
// passing it to React. The most reliable way is usually `String(value)`.
//
// 要解决此问题,在将此对象或符号值传递给 React 之前,将其强制转换为字符串。最可靠的方法通常
// 是使用 `String(value)`。
//
// To find which value is throwing, check the browser or debugger console.
// Before this exception was thrown, there should be `console.error` output
// that shows the type (Symbol, Temporal.PlainDate, etc.) that caused the
// problem and how that type was used: key, atrribute, input value prop, etc.
// In most cases, this console output also shows the component and its
// ancestor components where the exception happened.
//
// 要找出哪个值引发了异常,请检查浏览器或调试器控制台。在抛出此异常之前,应该有 `console.error` 输出
// 显示导致问题的类型(Symbol、Temporal.PlainDate 等)以及该类型的使用方式:键、属性、输入值属性等。
// 在大多数情况下,这些控制台输出还显示了发生异常的组件及其祖先组件。
//
return '' + (value as any);
}