JavaScript, React, Redux
Введение в чистые функции
Чистые функции широко используются в качестве строительных блоков в функциональном программировании из-за их предсказуемости и возможности повторного использования.
Есть несколько характеристик, которые определяют функцию как «чистую».
- Если задан тот же ввод, вы получите тот же результат.
- Никаких побочных эффектов.
Прогнозируемый результат
Мы можем передать аргумент чистой функции и знать, что независимо от того, сколько раз мы запускаем этот фрагмент кода, мы получим тот же результат.
Посмотрите этот пример ниже. Независимо от того, что мы присвоим x, мы получим x в квадрате.
function getSquare(x) { return x * x; }
Без побочных эффектов / Независимый
Чистые функции всегда неизменны. Они не должны изменять никаких внешних переменных. Рассмотрим разницу между отображением массива и возвратом нового массива и использованием .push () для переноса нового элемента в существующий массив. Лестница изменит исходный массив и считается нечистой. Опасность изменения разделяемых состояний состоит в том, что другая функция могла полагаться на это исходное состояние. Теперь, когда он был изменен, это может привести к появлению ошибок, которые может быть трудно отследить.
Тест на чистоту
Давайте применим это понимание на практике.
Какой из этих примеров чистый, а какой нечистый?
Option A: function double(x) { return x + x; } function doubleAll(list) { return list.map(double); }
Option B: function double(x) { networkCall(x); return x + x; } function doubleAll(list) { for (let i = 0; i < list.length; i++) { list[i] = double(list[i]); } return list; }
Ответ:
Вариант А чистый! Мы можем ожидать, что вернемся к совершенно новому массиву, который был создан путем сопоставления исходного массива, но никак не видоизменив его.
Вариант B является нечистым, потому что он зависит от вывода сетевого вызова и перебирает список элементов, чтобы вернуть измененный исходный список. Если бы какие-либо другие функции зависели от этого списка, это могло бы вызвать сбой нашей программы или просто не вести себя так, как мы планировали.
Использование React и Redux
При работе с React ваше приложение может состоять из комбинации классовых и функциональных компонентов. Разница в том, что функциональные компоненты состоят из чистых функций и, следовательно, не содержат никаких состояний. Они не должны изменять какое-либо внешнее или разделяемое состояние. Внедрение функциональных компонентов везде, где вы можете, предпочтительнее для оптимизации, поскольку они являются самыми простыми и наиболее часто используемыми компонентами. Также стоит отметить, что эти функциональные компоненты не предназначены для использования методов жизненного цикла.
Один из ключевых принципов Redux заключается в том, что для обновления глобального дерева состояний с любыми входящими изменениями требуются чистые функции. Мы называем эти чистые функции редукторами. Они принимают предыдущее состояние и действие, которое мы обеспечиваем, чтобы вернуть следующее состояние, оставляя предыдущее состояние неизменным.
На диаграмме ниже вы можете увидеть, как мы обновляем состояние в Redux, не изменяя исходное состояние. Мы отправляем действие, которое передается редуктору. Редуктор принимает информацию о текущем состоянии и использует чистую функцию для обновления хранилища новым состоянием на основе действия, которое мы дали в качестве аргумента.
В заключение
Согласно документации Redux, «писать неизменяемую логику обновления вручную сложно, а случайное изменение состояния в редукторах - единственная наиболее частая ошибка, которую делают пользователи Redux».
Существует библиотека JavaScript под названием Immer, которая принимает наш изменяемый код и преобразует его в приемлемую чистую функцию. Существует даже специальный метод createSlice, который вы можете использовать, автоматически включающий Immer. Вы можете прочитать больше об этом здесь".
А до тех пор стоит научиться распознавать и формулировать чистые функции везде, где это возможно, для более оптимизированного и многократно используемого кода.