npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

effector-action

v1.1.0

Published

This library provides api which allows changing the state of stores or calling events in an imperative style without breaking the static approach of the Effector. This should eliminate the problem when one synchronous task is split into several samples, o

Downloads

389

Readme

Effector Action

This library provides api which allows changing the state of stores or calling events in an imperative style without breaking the static approach of the Effector. This should eliminate the problem when one synchronous task is split into several samples, or when the task turns into a mess of nested samples, conditions and splits. Therefore this abstraction can serve as a convenient replacement for one or more synchronous operators that are responsible for a single action.

Install

npm i --save effector-action

This requires effector >=23 and patronum >=2.1.0.

Usage

Change units

All units in target are available for change in fn. To change the value of a store or trigger an event simply call it and pass the appropriate value.

import { createAction } from 'effector-action';

const $store = createStore('');
const event = createEvent<number>();
const effectFx = createEffect<boolean, void>();

const changeValues = createAction({
  target: {
    $store,
    event,
    effectFx,
  },
  fn: (target) => {
    target.$store('foo');
    target.event(123);
    target.effectFx(false);
  },
});

changeValues();

Or you can change single unit

import { createAction } from 'effector-action';

const $store = createStore('');

const changeValue = createAction({
  target: $store,
  fn: (target) => {
    target('foo');
  },
});

changeValue();

You can change the specified units by condition

const changeValues = createAction({
  target: {
    $store,
    event,
    effectFx,
  },
  fn: (target) => {
    const condition = Math.random() > 0.5;

    if (condition) {
      target.$store('foo');
    } else {
      target.event(123);
    }

    target.effectFx(condition);
  },
});

changeValues();

Сhange store using reducer func

You can change store values ​​using the reducer function and based on the current state of the store.

const inc = createAction({
  target: {
    $counter,
  },
  fn: (target) => {
    target.$counter((counter) => counter + 1); // get current counter state and increment it
  },
});

Reset store

You can just reset store using the reinit method.

const $store = createStore('');

const changeValues = createAction({
  target: {
    $store,
  },
  fn: (target) => {
    target.$store.reinit();
  },
});

Clock

To run fn you need to trigger the clock. Clock can be specified in the clock field

createAction({
  clock: $store,
  target,
  fn,
});

createAction({
  clock: [$store, event],
  target,
  fn,
});

Сlock value is available in the last parameter of fn

const clock = createEvent<string>();

createAction({
  clock: [$store, event],
  target,
  fn: (target, clock) => {
    // clock is string
    target.$someStore(clock.toLowerCase());
  },
});

If clock is not specified then createAction will return event as clock

const clock = createAction({
  target,
  fn,
});

To specify the type for the returned clock you need to manually add it

const clock = createAction({
  target,
  fn: (target, clock: string) => {}, // specify clock type
});

// clock = Event<string>

Alternative api for external clock usage

You can specify external clock in the first argument.

const inputChanged = createEvent<string>();
const $lowerCaseInput = createStore('');

createAction(inputChanged, {
  target: { $lowerCaseInput },
  fn: (target, clock) => {
    target.$lowerCaseInput(clock.toLowerCase());
  },
});

I recommend using this method because you can see the clock name even if the code blocks are folded in your ide.

VS When clock is in the config you don't see its name

Source

Analog of source from sample. Source values ​​are available in the second parameter of fn

const clock = createAction({
    source: {
        foo: $store1,
        bar: $store2
    }
    target,
    fn: (target, { foo, bar }, clock: string) => {};
})

Removing dollar prefix from store names in source

To avoid duplication of store names in the source, dollar prefixes are removed automatically

const clock = createAction({
    source: {
        $longStoreName1 // short naming
        longStoreName2: $longStoreName2 // default naming
    }
    target,
    fn: (
      target, { longStoreName1, longStoreName2 }, clock: string) => {
        target.doSomething(longStoreName1) // dollar prefix removed!
      };
})

Limitation

Functions that change units should be called no more than once.

If it was called multiple times, only the last call will be counted.

const changeValues = createAction({
  target: {
    $store,
  },
  fn: (target) => {
    target.$store('foo');
    target.$store('bar'); // only last call will be counted
  },
});

changeValue();

$store; // state = bar

Only sync function allowed in fn

const changeValues = createAction({
  target: {
    $users,
  },
  fn: async (target) => {
    const data = await loadUsers();

    target.$users(data); // will not work!
  },
});

Under the hood

Under the hood it's an abstraction over sample and patronum/spread.

const clock = createEvent();

createAction({
  clock,
  source: { foo: $foo, bar: $bar },
  target: {
    event,
    $store,
    effectFx,
  },
  fn: (target, { foo, bar }, clock) => {
    const condition = Math.random() > 0.5;

    if (condition) {
      target.event(foo);
    } else {
      target.$store(bar);
    }

    target.effectFx(clock);
  },
});

// is equivalent to

sample({
  clock,
  source: { foo: $foo, bar: $bar },
  fn: ({ foo, bar }, clock) => {
    const result = {};

    const condition = Math.random() > 0.5;

    if (condition) {
      result['event'] = foo;
    } else {
      result['$store'] = bar;
    }

    result['effectFx'] = clock;

    return result;
  },
  target: spread({
    event,
    $store,
    effectFx,
  }),
});