Sofware Development

Neox data structure compatible with redux hooks

June 16, 2020

by

tintef

## What’s Neox?Neox is a really tiny JavaScript library (just **269B** when minified and gzipped!) that exposes a function returning a simple data structure from any given plain JavaScript object.## The problem it solvesWhile using Immutable to create our [Redux reducers](https://redux.js.org/basics/reducers), we found an issue in the way it interacts with [React’s `useEffect` hook](https://reactjs.org/docs/hooks-effect.html) (_"the Effect Hook lets you perform side effects in function components"_). As Immutable Maps return a new reference every time the `toJS` function is called and **also** a new reference for the inner properties, the callback provided to a `useEffect` hook was being triggered on every mutation to the reducer, even if the desired property hadn’t changed at all!In order to solve this, we had to get rid of Immutable (see this [issue](https://github.com/reduxjs/redux/issues/3699)), but we wanted to avoid changing a lot of code on every reducer. Neox data structure is built to return a new reference every time the `toJS` function is called **but not to change** the reference of the inner properties, the callback provided to a `useEffect` hook is only triggered when the desired property has changed!## Neox data structure overviewFirst, let’s see how we can use the library to create a simple Neox data structure from an object and store it in a constant called `state`.```jsimport fromJS from "@neocoast/neox";const state = fromJS({ loading: false, user: { id: 1, username: "tintef", },});console.log(state);// Object {values: Map, toJS: function toJS(), set: function ()}```As can be seen, the result of the `console.log` statement, our `state` has just three properties:- `values`: [Map object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) containing all the entries from the object passed as a parameter to the `fromJS` function.- `toJS`: function that returns a new object on each call. This object contains every property inside the `values` Map.- `set`: handy function to mutate the `values` property.## But… why this approach?Long story short **we wanted to replace every occurrence of Immutable’s `fromJS` function with the least effort possible**.We were using the following piece of code to create a reducer:```jsimport { fromJS } from 'immutable';const intialState = fromJS({ loading: false, user: { id: 1, username: 'tintef', },});export default reducer(state = initialState, action) => { switch (action.type) { case 'SET_LOADING': return state.set('loading', action.payload); case 'SET_USER': return state.set('user', action.payload); }}```Then, we can access its properties from a React component doing:```jsimport React from 'react';import { useSelector, shallowEqual } from 'react-redux';const Component = () => { const { user } = useSelector(state => state.toJS(), shallowEqual); ...}```As Neox data structure shares the functions we are using from Immutable Maps, **Neox allows us to just change the `import` statement on each reducer!** No more changes. Pretty cool, huh?```jsimport fromJS from '@neocoast/neox';const intialState = fromJS({ loading: false, user: { id: 1, username: 'tintef', },});export default reducer(state = initialState, action) => { switch (action.type) { case 'SET_LOADING': return state.set('loading', action.payload); case 'SET_USER': return state.set('user', action.payload); }}```Liked the idea? Check out the [repository](https://github.com/NeoCoast/neox) on Github!