# Introduction

!["I don't like sand. It's coarse and rough and irritating and it gets everywhere. Not like here. Here everything is soft and smooth."](https://327675532-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LGM0OjeTpXogjoKVOvv%2F-LGg2Gu1LIVfMm-5-ff0%2F-LGg2OemPcFErq8u6g_o%2Frs_hero_alt.006.png?alt=media\&token=10e22e59-1c9d-40bc-9f68-c8655a2f909f)

## Installation

Using npm:

> ```
> npm install redux-sands
> ```

Using yarn:

> ```
> yarn add redux-sands
> ```

## Basics

`redux-sands` gives you a single class as default export, from now on called `ReduxWrapper`. Here's a simple example that demonstrates how you could use it:

```javascript
import ReduxWrapper from "redux-sands";
import component from "./component";

// Instantiate the wrapper.
const wrapper = new ReduxWrapper({ called: "example" });

// Simply add the initial state, the component for render + a reducer.
wrapper
  .add({ initState: { count: 0 } })
  .add({ component })
  .add({ update: (state, action) => ({ ...state, ...action }) });

// Expose the redux-wrapper as any other redux-component.
export default wrapper.connection;
export const reducer = wrapper.reducer;
```

And now let's call it:

```javascript
class Comp extends PureComponent {
  render() {
    // When using 'ReduxWrapper', only an object as param is allowed.
    // Provide your values then via that object.
    return (
      <div onClick={() => this.props.update({ count: this.props.count + 1 })}>
        Increment
      </div>
    );
  }
}
```

As far as basic use cases go, that's it! No more hassle with manually creating actions, mappings and endless switches. Action-types get inferred automatically, as well as the linking to the reducer. You can focus on the actual app logic without having to deal with refactoring etc.&#x20;

{% hint style="warning" %}
`redux-sands` only works when calling the reducer with an object as param. You have to provide your state-changing values there.
{% endhint %}

## Importing

Furthermore, `ReduxWrapper` provides additional skills to simplify redux-usage:

```javascript
...

wrapper
  .add({ initState: { count: 0 } })
  .add({ component })
  .add({ update: (state, action) => ({ ...state, ...action }) })
  .import({ reducer: { otherReduxComp: ["reset", { origin: "delete", as: "otherDelete" }] } })
  .import({ state: { otherReduxComp: ["schemas"] } });

// Expose the redux-wrapper as any other redux-component.
// Important: 'saga' has to be exported when using 'import(...)' and integrated into the store-middleware.
export default wrapper.connection;
export const reducer = wrapper.reducer;
export const saga = wrapper.saga;
```

You're able to import reducers as well as state-props from other `ReduxWrapper`s in a dead-simple fashion. As demonstrated above, you can either import them 'as-is' or apply renaming.&#x20;

{% hint style="warning" %}
When importing reducers, you have to hook up the saga-export to the saga-middleware in your app. Else the action won't get fired.

If you don't have it installed yet, [here's the project](https://redux-saga.js.org).
{% endhint %}

#### Behind the scenes

`redux-sands` internally uses proxies to import reducers from other comps. This is necessary b/c we can't guarantee that the component we're importing from has already been instantiated. Therefore,  when an import is declared, the wrapper instance creates a unique proxy for that action. Upon calling, this proxy gets fired, which itself fires saga to dispatch the actual action.&#x20;

This race-condition doesn't occur when statically importing the reducers to your store. But since we're working here at runtime, redux may not find the other's reducer during its init, since it hasn't been created yet.

Saga is necessary, b/c dispatching actions in other reducers is a non-pattern. Hence we're dispatching the requested action as a controlled side effect via saga.

## Saga-integration

Last but not least, as hinted above, `redux-saga` is also supported. Here's how:

```javascript
...

wrapper
  .add({ initState: { data: {} } })
  .add({ component })
  .add({
    refetch: {
      fn: (state, { data = {} }) => {
        return { ...state, data };
      },
      withSaga: {
        takeEvery: function*(action) {
          const { url, result, put } = action;

          try {
            const data = yield fetch(url);
            yield put({ ...result, data });
          } catch (e) {
            yield put({ ...result, error: e });
          }
        }
      }
    }
  })

// Expose the redux-wrapper as any other redux-component.
export default wrapper.connection;
export const reducer = wrapper.reducer;
export const saga = wrapper.saga;
```

Here you can see a dummy-implementation that leverages the saga-integration. You provide both the standard reducer-function and a saga-function. The specific saga-fn gets derived by its key with the value representing the actual generator-method used by saga. After the async calls are done, you place your params in the 'put' method, which is provided in the action (including `call` from saga). The params then get passed to the reducer, where stuff gets done as usual.&#x20;

{% hint style="info" %}
All saga helpers, effect creators and effect combinators are supported, as listed [here](https://redux-saga.js.org/docs/api/).

For a guide on how to use them, go [here](https://neue-moderne.gitbook.io/redux-sands/api-1/add#add-reducer).
{% endhint %}

That's it for an overview. For detailed info, take a look at the API-specs following.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://neue-moderne.gitbook.io/redux-sands/master.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
