Quick Introduction to Recoil Selectors

Selectors are powerful utility functions in recoil. It is so powerful that it can write to a state and read from a state even simultaneously. With selectors, we can write pure functions out of the box.

What are selectors?

A selector is an higher-order function that takes an option as argument, it allows for fetching real time access to a piece of state and return any manipulation of the fetched state without necessarily mutating the fetched state. According to the docs, it's a pure function that returns a derived state.

What Selectors are used for?

Selectors can be used for 2 major things:

  • function as a getter: in this case, when it is used to read a state
  • function as a setter: that is update or change the value of a state, write to a state in short.

It is also important to know all this can happen synchronously or async-ly.

What is the hype with Selectors?

The introduction screamed the hype, pure. Thanks to selectors, you need not to bother if you are writing mutable or immutable function inside it, you just won't be mutating the state, hence pure functions.

This is because the selectors has been made to caution you when you try making mutations in your code and does the fetching and updates on your behalf. However, if need be, you can flag for a mutation: this can be done when you set dangerouslyAllowMutability? property in it options as true.

How to write a Selector?

The selector takes an option as argument and then make changes on demand. This option can be atoms or other selectors that is simple read from or return a re-evaluation when something changes in either of them.

However to write one, here are the most important things to take note of

  1. key: This must always be present in your options. If you forget anything, please don't forget this. Your selector could silently malfunction when this is missing in your options. The key is used to identify a selector internally and it should be unique.

  2. get: it is a function that gets or reads the value for a recoil state, this can be atoms or any other selectors that is read from to make re-evaluations.

  3. set: this is a function that takes a an object of callbacks as argument. It allows us to write to a state.

The selector option has five properties and I have only decided to discuss the three that is more friendly for us and more useful to this article. To get a more detailed view, visit the docs.

Let's build a Tick app with our shinny new knowledge

They say learning to code is not sufficient, until one practices. Well this won't be another long section. We would be building a small app that increase a number on a tick simple. See the app here, codesandbox.io/s/xenodochial-engelbart-ci9y8.

The only amazing thing is how we did almost everything with selectors alone. I wanted to stress the power of selectors and making us see it in action.

Since the codesanbox has it all sorted out, I will be moving really quick here. Please use it as a reference.

// this can be found at store/atom.js
// I made a state to keep up with things

import {atom} from "recoil"

const timerState = atom({
  key: "timerState",
  default: 1,
})

export {timerState}
// store/selectors.js
// notice my key and how I defined the get and set properties

const getTicks = selector({
  key: "getTicks",
  get: ({ get }) => {
    let prevState = get(timerState);
    const state = prevState.toString().length < 2 ? `0${prevState}` : prevState;
    return state;
  },

  set: ({ set, get }, newValue) => {
    let s = get(timerState);
    set(timerState, s + newValue);
  }
});
// we used useRecoilValue to read
// and useSetRecoilValue to write


export default function App() {
  const ticks = useRecoilValue(getTicks);
  const setTimer = useSetRecoilState(getTicks);
  return (
    <div className="App">
      <h1>Recoil Selectors</h1>
      <h2>Performant selectors</h2>
      <div>{ticks}</div>
      <Btn setTimer={setTimer} />
    </div>
  );
}

// Btn component where I used the setTimer callback
export const Btn = ({ setTimer }) => {
  return (
    <div className="flex gap">
      <button onClick={() => setTimer(1)}>1</button>
      <button>2</button>
    </div>
  );
};

Take Home Work

Add an onclick handler so that when button 2 is clicked, it increases the timer, well tick should have been the proper word instead of timer Lol, with two.

That's all for now

I will be back some other time. But I hope this article helped you in one way or the other. If it did, please send me hi on twitter, kelvinsekx, I love making new friends, Thanks.