Skip to content

Actions

Overview

Actions in neutrix provide a way to handle complex state changes and async operations. They're particularly useful when you need to:

  • Coordinate multiple state updates
  • Handle async operations like API calls
  • Process data before updating state
  • Manage loading and error states

When to Use Actions

Use actions when you need to:

  • Call an API or do something async
  • Update multiple things at once
  • Show loading states
  • Handle errors

That's really it! The main thing to remember is: if you need to do something more complex than just set, use an action.

Creating actions

1. Using Store Action Creator

typescript
const store = createNeutrixStore({
  users: [],
  loading: false,
  error: null
});

const fetchUsers = store.action(
  async (store) => {
    store.set('loading', true);
    try {
      const users = await api.getUsers();
      store.set('users', users);
      return users;
    } finally {
      store.set('loading', false);
    }
  }
);

2. Using Initial State (Hook Store Only)

typescript
const useStore = createNeutrixStore({
  count: 0,
  increment: async (state) => {
    return { count: state.count + 1 };
  }
});

Using Actions in Components

1. Using useNeutrixAction Hook

typescript
function UserList() {
  const { loading, error, execute } = useNeutrixAction(
    async (store) => {
      const users = await api.getUsers();
      store.set('users', users);
    }
  );

  return (
    <div>
      <button onClick={execute} disabled={loading}>
        Load Users
      </button>
      {error && <div>Error: {error.message}</div>}
    </div>
  );
}

2. Using Store-Created Actions

typescript
function UserManager() {
  const { loading, error, execute } = useNeutrixAction(
    async (store, userId: string, data: UserData) => {
      store.set(`users.${userId}.updating`, true);
      try {
        const user = await api.updateUser(userId, data);
        store.set(`users.${userId}`, user);
      } finally {
        store.set(`users.${userId}.updating`, false);
      }
    }
  );

  return <UserForm onSubmit={execute} />;
}

Action features

Batch updates

typescript
const checkout = store.action(async (store) => {
  store.batch([
    ['cart', []],
    ['orderStatus', 'processing'],
    ['lastOrder', { id: '123', items: [] }]
  ]);
});

Type safety

typescript
interface UserState {
  users: User[];
  loading: boolean;
  error: string | null;
}

const useUserStore = createNeutrixStore<UserState>({
  users: [],
  loading: false,
  error: null
});

const fetchUsers = useUserStore.store.action(
  async (store) => {
    store.set('loading', true); 
    try {
      const users = await api.getUsers();
      store.set('users', users);
    } catch (error) {
      store.set('error', error.message); 
    }
  }
);