> For the complete documentation index, see [llms.txt](https://valonekowd78.gitbook.io/tech-notes/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://valonekowd78.gitbook.io/tech-notes/react/duck.md).

# Duck

## Define \`createReducer\` helper

```javascript
const createReducer = (initialState = {}, handlers = {}) => (state, action) => {
  const nextState = produce(state, draft => {
    if (handlers[action.type]) {
      return handlers[action.type](draft, action)
    }
  })

  return nextState
}
```

{% hint style="info" %}
`produce` is a function of [immer](https://github.com/immerjs/immer)
{% endhint %}

## Declare initial state

```javascript
const initialState = {
  locale: 'en',
  theme: 'light',
}
```

## Declare action types

```javascript
const types = new Proxy({
  CHANGE_LOCALE: 'CHANGE_LOCALE',
  CHANGE_THEME: 'CHANGE_THEME',
}, {
  get: (target, prop) => `app_name/domain_namespace/${target[prop]}`,
})
```

{% hint style="info" %}
prefix `app_name/domain_namespace` for separating your action from 3rd parties actions such as [connected-react-router](https://github.com/supasate/connected-react-router), [redux-saga](https://github.com/redux-saga/redux-saga) when working with redux devtools
{% endhint %}

## Declare action creators

```javascript
const actions = {
  changeLocale: newLocale => ({ type: types.CHANGE_LOCALE, payload: newLocale }),
  changeTheme: newTheme => ({ type: types.CHANGE_THEME, payload: newTheme }),
}
```

## Declare reducer

```javascript
const reducer = createReducer(initialState, {
  [types.CHANGE_LOCALE]: (draft, { payload }) => {
    draft.locale = payload
  },
  [types.CHANGE_THEME]: (draft, { payload }) => {
    draft.theme = payload
  },
})
```

## Declare selectors

```javascript
const selectors = {
  selectApp: state => state.app || initialState,
  makeSelectLocale() {
    return createSelector(this.selectApp, ({ locale }) => locale)
  },
  makeSelectTheme() {
    return createSelector(this.selectApp, ({ theme }) => theme)
  },
}
```

{% hint style="info" %}
`createSelector` is a function of [reselect](https://github.com/reduxjs/reselect)
{% endhint %}
