Skip to content

v2.4.0

Choose a tag to compare

@ctrlplusb ctrlplusb released this 14 Jun 13:59

Big Release

This release is the culmination of a lot of consideration over the APIs as they had evolved up to v2.3.0. I took the time to consider the parts of the API which I felt were ambiguous, inconsistent, ornot in line with the "easy peasy" premise.

Instead of going for a big bang breaking change release I have aimed for a minor release, and have subsequently marked a few of the APIs as being deprecated. I highly encourage you to migrate to the new APIs as soon as you can.

The website itself is a work in progress. Writing docs is really hard. Especially trying to keep them clear and consistent. I've gotten them to a base level for now, but in my opinion they still need to be taken much further. The Typescript and Testing sections are notable sections that lack completion. I'll get to them, I promise.

New Website

https://easy-peasy.now.sh

🎉

selector

❗️❗️❗️ THIS HELPER HAS SINCE BEEN DEPRECATED ❗️❗️❗️
https://github.com/ctrlplusb/easy-peasy/releases/tag/v2.6.0

This API deprecates the previous select API. It addresses some performance concerns and introduces runtime arguments as a first class citizen within the API.

Migrating your code from select to selector

Before:

const todosModel = {
  items: [],
  firstTodo: select(state => 
    state.items.length > 0 ? state.items[0] : undefined
  )
}

After:

import { selector } from 'easy-peasy';

const model = {
  todos: [],
  firstTodo: selector(
    [state => state.todos],
    (resolvedState) => {
      const [todos] = resolvedState;
      return todos.length > 0 ? todos[0] : undefined;
    }
  )
}

The above looks more verbose, but it provides very useful optimisations that will allow your applications to scale. Please read the full docs on the new API here.

debug

This new API allows you to unwrap your state within your actions so that you can console.log them etc.

import { debug } from 'easy-peasy';

const model = {
  myAction: action((state, payload) => {
    console.log(debug(state)); // 👈 prints the "native" state representation
  })
};

action and thunk listeners

Actions and thunks have been extended to allow a configuration when defining them. Both of them support a listenTo configuration value. This value allows you to configure the action or thunk to listen to a target action or thunk.

This API deprecates the previous listen API. We chose to do this deprecate the listen API as this action/thunk based listener implementation provides us with the following benefits:

  1. The ability to see our listener actions/thunks being dispatched in the dev tools
  2. The ability to short circuit the underlying reducer, providing performance benefits (this will be realised when we move to v3 and remove the deprecated APIs)
  3. The ability to more easily test our listeners as we can manually dispatch them in our tests which allows us to test them in much the same manner as we would our standard actions and thunks.

Migrating your code from listen to listener action and thunk

Before:

const todosModel = {
  items: [],
  addTodo: action((state, payload) => {
    state.items.push(payload);
  })
};

const auditModel = {
  log: [],
  listeners: listen(on => {
    on(todosModel.addTodo, action((state, payload) => {
      state.logs.push(`Added todo: ${payload}`);
    });
    on(todosModel.addTodo, thunk((actions, payload) => {
	  console.log(`Added todo: ${payload}`);
    });
  })
};

After:

const todosModel = {
  items: [],
  addTodo: action((state, payload) => {
    state.items.push(payload);
  })
};

const auditModel = {
  log: [],
  onAddTodoActionListener: action(
    (state, payload) => {
      state.logs.push(`Added todo: ${payload}`);
    },
    { listenTo: todosModel.addTodo }
  ),
  onAddTodoThunkListener: thunk(
    (actions, payload) => {
	  console.log(`Added todo: ${payload}`);
    },
    { listenTo: todosModel.addTodo }
  )
  })
};

Hooks

We have created new aliases for the hooks. The previous ones are considered deprecated.

Instead of useActions, please use useStoreActions.

Instead of useDispatch, please use useStoreDispatch.

Instead of useStore, please use useStoreState.

Migrating your code to new hooks

Before:

import { useActions, useDispatch, useStore } from 'easy-peasy';

function MyComponent() {
  const addTodo = useActions(actions => actions.todos.addTodo);
  const todos = useStore(state => state.todos.items);
  const dispatch = useDispatch();
}

After:

import { useStoreActions, useStoreDispatch, useStoreState } from 'easy-peasy';

function MyComponent() {
  const addTodo = useStoreActions(actions => actions.todos.addTodo);
  const todos = useStoreState(state => state.todos.items);
  const dispatch = useStoreDispatch();
}

createComponentStore

We have introduced a new API that allows you to create a store for a component.

createContextStore

We have introduced a new API that allows you to create multiple shared stores.

Store

The store instance has a few new APIs and some deprecated ones against it.

We have added the following:

  • getActions (Function)

    Returns the actions of your store.

  • useStoreActions (Function)

    The useStoreActions hook. This is typically useful when using Typescript with Easy Peasy, as this hook will be typed against your store.

  • useStoreDispatch (Function)

    The useStoreDispatch hook. This is typically useful when using Typescript with Easy Peasy, as this hook will be typed against your store.

  • useStoreState (Function)

    The useStoreState hook. This is typically useful when using Typescript with Easy Peasy, as this hook will be typed against your store.

By attaching the hooks to the store this plays really nicely with Typescript as the hooks will naturally have all the typing information available on them. This deprecates the createTypedHooks API.

The following are considered deprecated:

  • triggerListener (Function)

    Allows you to trigger a listen registration of your model with the provided action.

  • triggerListeners (Function)

    Allows you to trigger all registered listeners across the store that are listening to the provided action.

As the listen API is deprecated, the above functions that allow triggering of them are also deprecated.