Redux против Recoil: что использовать?
Facebook недавно объявил о новой библиотеке управления состоянием для React под названием Recoil. Несмотря на то, что он все еще находится на ранней стадии эксперимента, он получил много ажиотажа с 8000+ звезд на Github.
Поскольку Redux является самой популярной библиотекой управления состояниями, используемой для React, естественно захотеть провести сравнение с Recoil - когда имеет смысл использовать одну над другой?
Store vs Atom
В Redux у нас есть концепция централизованного хранилища, в котором хранятся все данные для нашего приложения.
В простом примере списка дел ваш store будет выглядеть примерно так:
{
listName: 'My cool to-do list',
tasks: {
'1': {
name: 'My first task',
}
}
}
Вместо этого Recoil разделяет ваше состояние на отдельные атомы. У вас будет один атом для listName
, а другой для tasks
. Вот как вы можете создать atom
для своих задач (взяты из документации Recoil):
const todoListState = atom({
key: 'todoListState',
default: [],
});
Пока я смотрел это видео ReactEurope, создатель Recoil, Дейв МакКейб, также представил возможность создания отдельных атомов для каждого из ваших элементов:
export const itemWithId =
memoize(id => atom({
key: `item${id}`,
default: {...},
}));
В нашем случае это будет включать создание отдельных атомов для каждого из tasks
.
Что делает Recoil более производительным?
Дейв МакКейб упомянул в комментарии на HackerNews :
«Ну, я знаю, что на одном инструменте мы увидели примерно 20-кратное ускорение по сравнению с использованием Redux. Это потому, что Redux - это O(n) в том смысле, что он должен спрашивать каждый подключенный компонент о необходимости повторной визуализации, тогда как мы можем быть O(1). "
Отдача может быть O(1), потому что при редактировании данных, хранящихся в атоме, только компоненты, подписанные на этот атом, должны будут повторно визуализироваться.
В нашем примере списка дел, если бы у нас было 20 отдельных задач, у нас было бы 20 отдельных атомов. Если мы отредактируем пятое задание, только пятое задание нужно будет перерисовать.
Redux это позволяет достичь того же эффекта с помощью селекторов:
// selector
const taskSelector = (id) => state.tasks[id];
// component code
const task = useSelector(taskSelector(id));
Таким образом, компоненту необходимо будет выполнить повторную визуализацию только при повторной визуализации конкретной задачи.
Предостережение заключается в том, что каждый раз, когда изменяется какая-либо часть состояния, нашему taskSelector
придется пересчитывать себя.
Мы также можем использовать оптимизацию, например createSelector
, для сокращения дорогостоящих вычислений, но для этого еще нужно проверить, нужно ли сначала пересчитывать.
Я думаю, что эти оптимизации производительности означают, что Recoil может иметь смысл для огромных приложений, которые должны отображать большое количество компонентов на странице. Ваше обычное приложение, вероятно, будет хорошо работать с Redux, и я не думаю, что стоит переходить на Recoil только из-за потенциальных (возможно, несуществующих) преимуществ производительности.
Могут быть и другие причины, по которым вы можете перейти на Recoil - возможно, если вы считаете, что API имеет для вас больше смысла, чем Redux, или его проще использовать и понимать. Поскольку Recoil все еще находится в экспериментальной фазе, нужно будет подождать, чтобы увидеть, есть ли другие веские причины для перехода с Redux на Recoil.