La página de front-end tiene una pantalla blanca y el componente no se puede renderizar, debemos prestarle especial atención, veamos cómo se optimiza el código.
1. Se informará un error una vez que se deconstruya la variable
Antes de la optimización :
const App = (props) => {
const { data } = props;
const { name, age } = data
}
La regla de la asignación de desestructuración es que siempre que el valor a la derecha del signo igual no sea un objeto o una matriz, primero conviértalo en un objeto. Dado que
undefined
nonull
se pueden convertir en objetos, se informará un error al desestructurarlos y asignarlos.
Entonces, cuando lo data
sea , el código anterior informará un error. undefined
null
Después de la optimización :
const App = (props) => {
const { data } = props || {};
const { name, age } = data || {};
}
2. Valores por defecto poco fiables
Se estima que algunos estudiantes, al ver el código de la sección anterior, sienten que se puede optimizar aún más.
Optimizarlo de nuevo :
const App = (props = {}) => {
const { data = {} } = props;
const { name, age } = data ;
}
ES6 utiliza internamente el operador de igualdad estricta (
===
) para determinar si una variable tiene un valor. Por lo tanto, si el valor del atributo de un objeto no es estrictamente igual aundefined
, el valor predeterminado no tendrá efecto.
Entonces, si props.data
lo hace null
, ¡informará un error! const { name, age } = null
3. Los métodos de matriz solo se pueden llamar con matrices reales
Antes de la optimización:
const App = (props) => {
const { data } = props || {};
const nameList = (data || []).map(item => item.name);
}
Entonces viene el problema, cuando data
el resultado es que no hay 123
un método como , se reportará un error.data || []
123
123
number
map
Los métodos de matriz solo se pueden llamar con matrices reales, ni siquiera con matrices de tipo clase. Cómo juzgar data
que es una matriz verdadera Array.isArray
es la más confiable.
Optimizado:
const App = (props) => {
const { data } = props || {};
let nameList = [];
if (Array.isArray(data)) {
nameList = data.map(item => item.name);
}
}
Cuarto, cada elemento de la matriz no es necesariamente un objeto
Antes de la optimización:
const App = (props) => {
const { data } = props || {};
let infoList = [];
if (Array.isArray(data)) {
infoList = data.map(item => `我的名字是${item.name},今年${item.age}岁了`);
}
}
Una vez que data
cierto valor en la matriz es undefined
o null
, item.name
se debe informar un error y la pantalla puede volver a ser blanca.
Optimizado:
const App = (props) => {
const { data } = props || {};
let infoList = [];
if (Array.isArray(data)) {
infoList = data.map(item => `我的名字是${item?.name},今年${item?.age}岁了`);
}
}
?
El operador de encadenamiento opcional, si bien es útil, no se puede abusar. item?.name
se compilará en , el uso indebido puede provocar un aumento del tamaño del código después de la edición. item === null || item === void 0 ? void 0 : item.name
Después de la segunda optimización:
const App = (props) => {
const { data } = props || {};
let infoList = [];
if (Array.isArray(data)) {
infoList = data.map(item => {
const { name, age } = item || {};
return `我的名字是${name},今年${age}岁了`;
});
}
}
5. Quién puede llamar al método del objeto
Antes de la optimización:
const App = (props) => {
const { data } = props || {};
const nameList = Object.keys(data || {});
}
Los métodos de objeto se pueden usar siempre que la variable se pueda convertir en un objeto, pero undefined
no null
se puede convertir en un objeto. Al usar métodos de objetos en él, se informará un error.
Optimizado:
const _toString = Object.prototype.toString;
const isPlainObject = (obj) => {
return _toString.call(obj) === '[object Object]';
}
const App = (props) => {
const { data } = props || {};
const nameList = [];
if (isPlainObject(data)) {
nameList = Object.keys(data);
}
}
Seis, captura de error asíncrono/en espera
Antes de la optimización:
import React, { useState } from 'react';
const App = () => {
const [loading, setLoading] = useState(false);
const getData = async () => {
setLoading(true);
const res = await queryData();
setLoading(false);
}
}
Si queryData()
se informa un error durante la ejecución, ¿se debe a que la página sigue girando en círculos?
Optimizado:
import React, { useState } from 'react';
const App = () => {
const [loading, setLoading] = useState(false);
const getData = async () => {
setLoading(true);
try {
const res = await queryData();
setLoading(false);
} catch (error) {
setLoading(false);
}
}
}
Si los errores trycatch
detectados con await-to-js await
no se sienten elegantes, puede usar await-to-js para detectarlos correctamente.
Después de la segunda optimización:
import React, { useState } from 'react';
import to from 'await-to-js';
const App = () => {
const [loading, setLoading] = useState(false);
const getData = async () => {
setLoading(true);
const [err, res] = await to(queryData());
setLoading(false);
}
}
7. No todo se puede usar para JSON.parse
Antes de la optimización:
const App = (props) => {
const { data } = props || {};
const dataObj = JSON.parse(data);
}
JSON.parse()
El método convierte una cadena JSON válida en un objeto JavaScript. No es necesario verificar si una cadena es una cadena JSON válida o no. Solo use trycatch
para detectar errores.
Optimizado:
const App = (props) => {
const { data } = props || {};
let dataObj = {};
try {
dataObj = JSON.parse(data);
} catch (error) {
console.error('data不是一个有效的JSON字符串')
}
}
8. Datos de tipo de referencia modificados
Antes de la optimización:
const App = (props) => {
const { data } = props || {};
if (Array.isArray(data)) {
data.forEach(item => {
if (item) item.age = 12;
})
}
}
Si alguien usa App
esta función, no entenderá por qué el valor data
del medio age
es siempre el mismo , y no puede encontrar ningún lugar para modificar el valor del medio 12
en su código . Solo porque son datos de tipo de referencia. Para evitar la modificación accidental de datos al procesar datos de tipo de referencia en funciones públicas, se recomienda usar lodash.clonedeep para clonar primero.data
age
data
Optimizado:
import cloneDeep from 'lodash.clonedeep';
const App = (props) => {
const { data } = props || {};
const dataCopy = cloneDeep(data);
if (Array.isArray(dataCopy)) {
dataCopy.forEach(item => {
if (item) item.age = 12;
})
}
}
9. Ejecución concurrente y asíncrona de operaciones de asignación
Antes de la optimización:
const App = (props) => {
const { data } = props || {};
let urlList = [];
if (Array.isArray(data)) {
data.forEach(item => {
const { id = '' } = item || {};
getUrl(id).then(res => {
if (res) urlList.push(res);
});
});
console.log(urlList);
}
}
En el código anterior está el resultado final que no se puede imprimir. Debido a que es una función asíncrona, se agrega un valor después de la ejecución y el bucle se ejecuta de forma síncrona. Una vez que se completa la ejecución, es posible que no se complete, por lo que el resultado impreso no es el resultado final. console.log(urlList)
urlList
getUrl
urlList
data.forEach
data.forEach
getUrl
console.log(urlList)
urlList
Por lo tanto, debemos usar el formulario de cola para permitir que las funciones asíncronas se ejecuten simultáneamente, y luego usar Promise.all
el monitor para imprimir el valor después de que se ejecuten todas las funciones asíncronas urlList
.
Optimizado:
const App = async (props) => {
const { data } = props || {};
let urlList = [];
if (Array.isArray(data)) {
const jobs = data.map(async item => {
const { id = '' } = item || {};
const res = await getUrl(id);
if (res) urlList.push(res);
return res;
});
await Promise.all(jobs);
console.log(urlList);
}
}
10. Sobredefensivo
Antes de la optimización:
const App = (props) => {
const { data } = props || {};
let infoList = [];
if (Array.isArray(data)) {
infoList = data.map(item => {
const { name, age } = item || {};
return `我的名字是${name},今年${age}岁了`;
});
}
const info = infoList?.join(',');
}
infoList
¿Por qué debería seguirse más adelante ?
? El map
método de matriz debe devolver una matriz.
Optimizado:
const App = (props) => {
const { data } = props || {};
let infoList = [];
if (Array.isArray(data)) {
infoList = data.map(item => {
const { name, age } = item || {};
return `我的名字是${name},今年${age}岁了`;
});
}
const info = infoList.join(',');
}