Передача импортированного объекта стиля в пользовательский хук не работает должным образом - PullRequest
0 голосов
/ 12 февраля 2019

Я пытаюсь создать пользовательский хук, который будет обрабатывать некоторые слияния стилей Афродиты (https://github.com/Khan/aphrodite) для нас), но я получаю необычное поведение с передаваемым объектом стилей.

Вот мой хук: (план состоял в том, чтобы сочинять с помощью useMemo, именно поэтому он вообще хук)* пропускается styles prop, он будет объединен с чем угодно в baseStyles и даст окончательную таблицу стилей Aphrodite, которая будет использоваться для этого экземпляра компонента.

Я создал здесь простой репозиторий repro: https://github.com/bslinger/hooks-question

Ожидание: щелчок между двумя маршрутами изменит цвет текста в зависимости от того, были ли переданы реквизиты для переопределения этого стиля или нет.

Фактически: один раз для стилейбыли объединены, даже маршрут без дополнительных пропусков показывает его с переопределенным цветом.

Примечание: я понял, что после удаления useMemo это даже не технологияв действительности хук и понижение React до 16.7 привели к тому же самому поведению, так что я думаю, что это всего лишь вопрос Javascript или React?

1 Ответ

0 голосов
/ 12 февраля 2019

Ключом здесь является детальное понимание поведения 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
      )
    )
  };
};

Edit yqjjmmp21x

...