Ключом здесь является детальное понимание поведения Array.reduce .reduce
принимает два аргумента.Первый аргумент - это обратный вызов, который вы указали.Второй аргумент является необязательным и является начальным значением для аккумулятора (первый аргумент обратного вызова).Вот описание этого аргумента:
Значение, используемое в качестве первого аргумента для первого вызова обратного вызова.Если начальное значение не указано, будет использован первый элемент в массиве.Вызов метода Reduce () для пустого массива без начального значения является ошибкой.
Чтобы легче понять эффект этого, это поможет упростить ваш синтаксис.
Так долгопоскольку styles
и props.styles
не являются массивами (которых нет в вашем образце), следующее:
[...castArray(styles), ...castArray(props.styles)]
эквивалентно:
[styles, props.styles]
Так что вПри отсутствии начального значения функции reduce
аккумулятор будет первым элементом в вашем массиве: styles
.Поэтому, выполнив сценарий «withProps», вы изменили объект в styles.js
, и ничто не изменит его обратно на исходный зеленый.Если styles
был массивом (с использованием исходного кода), то этот побочный эффект возник бы с первым объектом стиля в этом массиве.
Чтобы это исправить, вам просто нужно указать начальное значение дляаккумулятор:
export const useStyles = (styles, props) => {
return {
styles: StyleSheet.create(
[...castArray(styles), ...castArray(props.styles)].reduce(
(agg, next) => merge(agg, next),
{} // Here's an empty object as the accumulator initial value
)
)
};
};