сегодня я понял, что я передавал объект между моими компонентами React, и он создавал два нежелательных эффекта: 1 - прослушивающий его useEffect срабатывал при каждом повторном рендеринге. 2- Конечно, было много повторных рендеров.
Итак, я попытался решить, сначала используя настраиваемый пользовательский эффект, который глубоко сравнивал объект:
use-deep-Compare-effect
Кстати, он прекрасно работал благодаря kentcddodds для этого ресурса.
Но это патч для решения проблемы, которая не работает в моем коде. Итак, я начал проверять React.memo и как сравнивать мои nextProps в функциональном компоненте. Я видел много функций в сети, но ни одна не предлагала гибкость для использования с каждым компонентом и выбора способа сравнения каждого реквизита.
Я создал эту функцию, я сделал ее , наиболее эффективную Я могу, и я хотел бы спросить вас, ребята, что вы думаете. Я уверен, что у вас есть идеи, чтобы улучшить его.
import deepEqual from 'deep-equal';
import { pick } from 'lodash';
/** Get difference between two arrays
* @param {} a1
* @param {} a2
*/
const getDiffArrays = (a1, a2) => {
const a = [];
const diff = [];
for (let i = 0; i < a1.length; i++) {
a[a1[i]] = true;
}
for (let i = 0; i < a2.length; i++) {
if (a[a2[i]]) {
delete a[a2[i]];
} else {
a[a2[i]] = true;
}
}
for (const k in a) {
diff.push(k);
}
return diff;
};
/**
* Return array with unique elements.
* ! How efficient is it? This is a function that is intensively used. Get
* @param {} arr
*/
const getDistinctKeysArray = (obj1, obj2) => [
...new Set([...Object.keys(obj1), ...Object.keys(obj2)]),
];
const compare = (obj1, obj2, compareFunc) => {
let res = true;
const keys = Object.keys(obj1);
for (let key = 0; res && res < keys.length; key++) {
res = compareFunc(obj1[keys[key]], obj2[keys[key]]);
}
return res;
};
/**
* Shallow comparison
*
* @param {} obj1
* @param {} obj2
*/
const compareShallow = (obj1, obj2) => obj1 === obj2;
/**
* Fast object comparison. It use JSON.stringfy. The problem is that is the order of the props change it
* will return false, between others
* @param {} obj1
* @param {} obj2
*/
const compareFastDeep = (obj1, obj2) =>
JSON.stringify(obj1) === JSON.stringify(obj2);
/**
* Function to compare object with flexibility.
* @param {} obj1
* @param {} obj2
* @param {} keysCompareFullDeep array keys that are going to be compare using a full deep method that is slowers but effective
* @param {} keysCompareFastDeep array keys that are going to be compare using a fast deep method that is not fully effective
*/
const compareHelper = (
prevProps,
nextProps,
keysCompareFullDeep = [],
keysCompareFastDeep = []
) => {
// Get keys for shallow compare
const keysCompareShallow = getDiffArrays(
getDistinctKeysArray(Object.keys(prevProps), Object.keys(nextProps)),
getDistinctKeysArray(keysCompareFastDeep, keysCompareFullDeep)
);
console.log(keysCompareShallow);
// Compare shallow
let res = compare(
pick(prevProps, keysCompareShallow),
pick(nextProps, keysCompareShallow),
compareShallow
);
console.log(res);
// Compare deep fast
res = res
? compareFastDeep(
pick(prevProps, keysCompareFastDeep),
pick(nextProps, keysCompareFastDeep)
)
: res;
console.log(res);
// Compare deep full
res = res
? deepEqual(
pick(prevProps, keysCompareFullDeep),
pick(nextProps, keysCompareFullDeep)
)
: res;
console.log(res);
return res;
};
export { compareHelper };
И использование:
SearcherComponent.propTypes = {
cars: PropTypes.array.isRequired,
filters: PropTypes.object.isRequired,
mainFilters: PropTypes.array.isRequired,
options: PropTypes.object.isRequired,
onFilterChange: PropTypes.func.isRequired,
onFilterDelete: PropTypes.func.isRequired,
onShowMoreFilters: PropTypes.func.isRequired,
showMoreFilters: PropTypes.bool.isRequired,
addToFavorite: PropTypes.func.isRequired,
deleteFavorite: PropTypes.func.isRequired,
onSaveFilterList: PropTypes.func.isRequired,
cleanFilterList: PropTypes.func,
chatRequest: PropTypes.func.isRequired,
goToCarExtendedInfo: PropTypes.func,
pagination: PropTypes.shape({
loading: PropTypes.bool,
setPaginationInfo: PropTypes.func,
sortBy: PropTypes.object.isRequired,
setSortBy: PropTypes.func.isRequired,
pagination: PropTypes.object,
}),
children: PropTypes.node.isRequired,
};
const Searcher = React.memo(SearcherComponent, (prev, next) =>
compareHelper(prev, next, ['pagination', 'cars', 'filters'], [])
);
export { Searcher as SearcherComponent };
Я знаю, что код немного запутан, я тестирую несколько реализаций.
Если мы получим хороший В порядке эффективности я планирую создать пакет publi c npm.
Пожалуйста, если кто-нибудь знает, имеет ли это смысл и как сделать это быстрее, скажите мне. При рассмотрении вопроса об изменении глубокий-равный на быстрый-глубокий-равный