# Patterns

### Consume feature in specific state

Sometimes you only want to consume a feature in a specific state, or states. This can be in an other feature or in a UI component. In these scenarios you should avoid using the hook and rather get the state of the feature as a prop from the outside.

```typescript
interface Props {
  someFeature: PickState<SomeFeature, 'SOME_STATE'>
}

const SomeUIComponent = ({ someFeature }: Props) => {
  
}
```

### Dynamic reducers

There are situations when the action handlers in the reducer needs access to state from other features or props. To avoid duplicating state you can make the reducer dynamic.

```typescript
const featureReducer = (someOtherFeatureState: SomeOtherFeature[0]) => createReducer<SomeFeature>({
  SOME_STATE: {
    SOME_HANDLER: () => ({...})
  }
})

interface Props {
  initialState?: State
}

const Feature = ({ initialState }: Props) => {
  const [someOtherFeatureState] = useSomeOtherFeature()
  const feature = useReducer(
    featureReducer(someOtherFeatureState),
    initialState
  )
}
```

### Lift action handlers

Sometimes you might have one or multiple action handlers across states. You can lift them up and compose them back into your transitions.

There are three parts to this patterns:

1. Only type what you need from an action, not the actions themselves
2. If you are consuming the current state, type it as any context (`State`) and optionally restrict it with properties and values you want to be available on that state
3. Always give `Transition` as the return type

You can define a single event handler:

```typescript
import { createReducer } from 'react-states';

const handleChangeDescription = (
  // Expressing that we allow any context, as long as it has "description" on it
  state: State & { description: string },
  // Expressing what we want from the event
  { description }: { description: string },

  // Allowing us to move into any state
): Transition => ({
  ...state,
  description,
});

const reducer = createReducer<Feature>({
  FOO: {
    DESCRIPTION_CHANGED: handleChangeDescription,
  },
  BAR: {
    DESCRIPTION_CHANGED: handleChangeDescription,
  },
});
```

Or multiple action handlers:

```typescript
import { createReducer } from 'react-states';

const globalActionHandlers = {
  DESCRIPTION_CHANGED: (state: State, { description }: { description: string }): Transition => ({
    ...state,
    description,
  }),
};

const reducer = createReducer<Feature>({
  FOO: {
    ...globalActionHandlers,
  },
  BAR: {
    ...globalActionHandlers,
  },
});
```

### Match all the things

You can use `match` for more than rendering a specific UI. You can for example use it for styling:

```typescript
<div
  css={match(someState, {
    STATE_A: () => ({ opacity: 1 }),
    STATE_B: () => ({ opacity: 0.5 }),
  })}
/>
```

You can even create your own UI metadata related to a state which can be consumed throughout your UI definition:

```typescript
const ui = match(someState, {
  STATE_A: () => ({ icon: <IconA />, text: 'foo', buttonStyle: { color: 'red' } }),
  STATE_B: () => ({ icon: <IconB />, text: 'bar', buttonStyle: { color: 'blue' } }),
});

ui.icon;
ui.text;
ui.buttonStyle;
```

### Subtype state for match

You might have functions that only deals with certain states.

```typescript
import { match, PickState } from 'react-states';

function mapSomeState(state: PickState<SomeFeature, 'A' | 'B'>) {
  return match(state, {
    A: () => {},
    B: () => {},
  });
}
```

`match` will infer the type of state and ensure type safety for the subtype.

### Base state

Sometimes you have multiple states sharing the same base state. You can best express this by:

```typescript
type BaseState = {
  ids: string[];
};

type State =
  | {
      state: 'NOT_LOADED';
    }
  | {
      state: 'LOADING';
    }
  | (BaseState &
      (
        | {
            state: 'LOADED';
          }
        | {
            state: 'LOADED_DIRTY';
          }
        | {
            state: 'LOADED_ACTIVE';
          }
      ));
```

This expresses the simplest states first, then indents the states using the base state. This ensures that you see these states related to their base and with their indentation they have "additional meaning".

### Nested states

You do not have to express the whole state at the root, you can split it up into nested states.

```typescript
type ValidationState =
  | {
      state: 'VALID';
    }
  | {
      state: 'INVALID';
    }
  | {
      state: 'PENDING';
    };

type State =
  | {
      state: 'ACTIVE';
      value: string;
      validation: ValidationState;
    }
  | {
      state: 'DISABLED';
    };
```

Now any use of `match` can be done on the sub states as well.

```typescript
match(state, {
  DISABLED: () => ({}),
  ACTIVE: ({ validation }) =>
    match(validation, {
      VALID: () => ({}),
      INVALID: () => ({}),
      PENDING: () => ({}),
    }),
});
```


---

# 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://react-states.csb.dev/patterns.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.
