Tornando o estado do Redux imutável

redux 4 de Out de 2017

Nas suas viagens pelo ecossistema do Redux já deve ter ouvido o termo Imutabilidade, mas o que significa isso e por que aplicar esse conceito no gerenciamento de estado?

Basicamente, dizer que algo é imutável é dizer que não pode sofrer alterações, sejam elas feitas pelo usuário ou derivadas de ações terceiras criadas pela aplicação. Mas pera aí, o estado do Redux precisa mudar, certo? Sim, e não.

O estado não é constante, seu valor muda diversas vezes durante a execução da aplicação, mas isso não quer dizer que ele é alterado. Seguindo o conceito de imutabilidade, o estado nunca é modificado e sim um novo estado é retornando sobrescrevendo o estado atual da aplicação.

Performance

Pense que ao modificar um objeto, a linguagem precisa percorrer todo objeto, buscando pelas propriedades alteradas e adicionando o novo valor à elas. A partir do momento que você segue o conceito de arquitetura Flux do Redux e mantenha um único objeto como estado global da sua aplicação, pense que cada alteração pode ocasionar essa busca por informações ser lenta e custosa para sua aplicação.

Em objetos imutáveis, quando um novo valor é retornado, ele sobrescreve o objeto inicial tornando todo processo mais rápido.

Imutabilidade nativa

O Javascript por padrão possui uma forma de tornar um objeto imutável utilizando o método Object.freeze da seguinte forma:

let obj = {
  name: "RocketZeat",
  site: "www.rocketseat.com.br"
};

obj.name = "RocketSeat"; // Funciona

let freezedObj = Object.freeze(obj);

freezedObj.name = "RocketSeeeeat"; // Não funciona


Dessa forma, o objeto se torna imutável e não é possível adicionar, alterar ou remover qualquer propriedade ou característica do objeto. No exemplo acima, o código não retorna nenhum erro, mas caso a notação 'use strict' for adicionada ao escopo do Javascript, um erro TypeError é disparado.

O grande problema de tornar um objeto imutável utilizando apenas o freeze do Javascript é sua performance que em alguns navegadores, como no Safari, é extremamente baixa.

Utilizando a biblioteca seamless-immutable

Uma das formas de unir as vantagens de ter um estado imutável com performance e praticidade na hora de modificar o estado no Redux é utilizando a biblioteca seamless-immutable. Com a lib, remover a mutabilidade de um objeto fica fácil:

import Immutable from 'seamless-immutable';

let obj = Immutable({
  name: "RocketSeat"
});

obj.name = "Rocketseeeat"; // Não funciona e dispara ImmutableError

E com a utilização do Immutable você pode utilizar o método merge para realizar o processo de copiar, alterar e retornar um novo objeto modificado com as novas informações:

let obj = Immutable({
  name: "RocketSeat"
});

obj.merge({ name: "Rocketseeeeat" }); // Funciona

Lembrando que o Immutable pode ser utilizado para qualquer tipo de estrutura de dados como inteiros, strings, arrays ou objetos e ele utiliza as funções nativas, como o freeze, unidas às técnicas próprias para tornar os objetos imutáveis.

Integrando ao Redux

Para integrar o seamless-immutable ao Redux basta utilizá-lo na hora de definir o estado inicial dos seus reducers, como por exemplo:

import Immutable from 'seamless-immutable';

const initialState = Immutable({
  data: [],
  loading: false
});

const reducer = (state = initialState, action) {
  switch (action.type)...
}

Dessa forma, quando você tentar alterar o estado da sua aplicação no reducer sem utilizar o merge, um erro será disparado e a ação será impedida.

Conclusão

Imutabilidade traz performance e organização ao seu projeto e integrá-la ao Redux torna todo processo ainda mais performático e prazeroso ao desenvolvedor já que o estado fica protegido à alterações inesperadas.

Ah, se gostou do post aproveita pra deixar aquele comentário sobre o que achou.

Marcadores

Diego Fernandes

Programador full-stack, apaixonado pelas melhores tecnologias de desenvolvimento back-end, front-end e mobile, é co-fundador e CTO na Rocketseat.