|
| 1 | +--- |
| 2 | +id: glossary |
| 3 | +title: Glossary |
| 4 | +sidebar_label: Glossary |
| 5 | +hide_title: true |
| 6 | +--- |
| 7 | + |
| 8 | +# Glossary |
| 9 | + |
| 10 | +This is a glossary of the core terms in Redux, along with their type signatures. The typealiases are |
| 11 | +defined in [Definitions.kt](todo) |
| 12 | + |
| 13 | +## State |
| 14 | + |
| 15 | +_State_ (also called the _state tree_) is a broad term, but in the Redux API it usually refers to |
| 16 | +the single state value that is managed by the store and returned by |
| 17 | +[`getState()`](api/Store.md#getState) or the property syntax [`state`](api/Store.md#getState). It |
| 18 | +represents the entire state of a Redux application. |
| 19 | + |
| 20 | +State can be any type of object, however data classes are well suited due to their `copy()` method |
| 21 | +for creating the new state. The contents and structure of the State are largely up to requirements |
| 22 | +of the app and the opinion of the implementer. In general, avoiding deeply nested structure makes |
| 23 | +creating the new state easier. Also this is the state of your App, not necessarily the state of |
| 24 | +your UI. Still, you should do your best to keep the state serializable. Don't put anything inside it |
| 25 | +that you can't easily turn into JSON. |
| 26 | + |
| 27 | +## Action |
| 28 | + |
| 29 | +An _action_ is an object that represents an intention to change the state. Actions are the only way |
| 30 | +to get data into the store. Any data, whether from UI events, network callbacks, system events, or |
| 31 | +other sources such as WebSockets needs to eventually be dispatched as an action. |
| 32 | + |
| 33 | +ReduxKotlin differs a bit from JS Redux in that since we have a statically typed language, we can |
| 34 | +use the type as indication of the action to be performed. Typically this is done with a `when` |
| 35 | +statement: |
| 36 | + |
| 37 | +```kotlin |
| 38 | +when (action) { |
| 39 | + is MyAction -> // handle MyAction |
| 40 | + ... |
| 41 | +} |
| 42 | +``` |
| 43 | + |
| 44 | +In JS redux, a `type` field is used to indicate the type of action performed. This approach can be |
| 45 | +used with ReduxKotlin, however type safety and IDE benefits will be lost. |
| 46 | + |
| 47 | +The structure of an action object is really up to you. Data classes are a good choice, since |
| 48 | +`toString()` is implemented and can be useful for logging. Data inside the action is used to update |
| 49 | +the state inside reducers. For example, an API request result may be inside an Action. |
| 50 | + |
| 51 | +See also [async action](#async-action) below. |
| 52 | + |
| 53 | +## Reducer |
| 54 | + |
| 55 | +```kotlin |
| 56 | +typealias Reducer<State> = (state: State, action: Any) -> State |
| 57 | +``` |
| 58 | + |
| 59 | +A _reducer_ (also called a _reducing function_) is a function that accepts an accumulation and a |
| 60 | +value and returns a new accumulation. They are used to reduce a collection of values down to a |
| 61 | +single value. |
| 62 | + |
| 63 | +Reducers are not unique to Redux—they are a fundamental concept in functional programming. Even most |
| 64 | +non-functional languages, like Kotlin, have a built-in API for reducing. In Kotlin, reduce is a |
| 65 | +[`function on collections and many types`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/reduce.html). |
| 66 | + |
| 67 | +In Redux, the accumulated value is the state object, and the values being accumulated are actions. |
| 68 | +Reducers calculate a new state given the previous state and an action. They must be _pure functions_ |
| 69 | +—functions that return the exact same output for given inputs. They should also be free of |
| 70 | +side-effects. This is what enables exciting features like [hot reloading and time travel](https://github.com/reduxjs/redux-devtools). |
| 71 | +These are possible with ReduxKotlin, but not yet documented and may required additional dev work. |
| 72 | + |
| 73 | +Reducers are the most important concept in Redux. |
| 74 | + |
| 75 | +> #### Note about threading |
| 76 | +> Reducers should always be ran on the same thread. This is to avoid any |
| 77 | +> race conditions with actions being processed. Which thread is used is up |
| 78 | +> to you and your team. Main thread has traditionally been used without any problems, |
| 79 | +> however there may be some situations where doing reducing fuctions on a background thread |
| 80 | +> would benefit performance. |
| 81 | +
|
| 82 | +_Do not put API calls into reducers._ |
| 83 | + |
| 84 | +## Dispatching Function |
| 85 | + |
| 86 | +```kotlin |
| 87 | +typealias Dispatcher = (Any) -> Any |
| 88 | +``` |
| 89 | + |
| 90 | +A _dispatching function_ (or simply _dispatch function_) is a function that accepts an action or an |
| 91 | +[async action](#async-action); it then may or may not dispatch one or more actions to the store. |
| 92 | + |
| 93 | +We must distinguish between dispatching functions in general and the base |
| 94 | +[`dispatch`](api/Store.md#dispatchaction) function provided by the store instance without any |
| 95 | +middleware. |
| 96 | + |
| 97 | +The base dispatch function _always_ synchronously sends an action to the store's reducer, along with |
| 98 | +the previous state returned by the store, to calculate a new state. It expects actions to be plain |
| 99 | +objects ready to be consumed by the reducer. |
| 100 | + |
| 101 | +[Middleware](#middleware) wraps the base dispatch function. It allows the dispatch function to |
| 102 | +handle [async actions](#async-action) in addition to actions. Middleware may transform, delay, |
| 103 | +ignore, or otherwise interpret actions or async actions before passing them to the next middleware. |
| 104 | +See below for more information. |
| 105 | + |
| 106 | +## Action Creator |
| 107 | + |
| 108 | +Action Creators are used in JS Redux, but are not as desirable in Kotlin. They are simply a function |
| 109 | +that creates an Action or Async Action. In Kotlin, since we are typically using Data classes this is |
| 110 | +not necessary. Data class constructors provide a nice syntax for creating actions. Using the Action |
| 111 | +Creator pattern in Kotlin works as well, and is really up to you as to how and where actions are |
| 112 | +created. |
| 113 | + |
| 114 | +Calling an action creator only produces an action, but does not dispatch it. You need to call the |
| 115 | +store's [`dispatch`](api/Store.md#dispatchaction) function to actually cause the mutation. Sometimes |
| 116 | +we say _bound action creators_ to mean functions that call an action creator and immediately |
| 117 | +dispatch its result to a specific store instance. |
| 118 | + |
| 119 | +If an action creator needs to read the current state, perform an API call, or cause a side effect, |
| 120 | +like a routing transition, it should return an [async action](#async-action) instead of an action. |
| 121 | + |
| 122 | +## Async Action |
| 123 | + |
| 124 | +An _async action_ is a value that is sent to a dispatching function, but is not yet ready for |
| 125 | +consumption by the reducer. It will be transformed by [middleware](#middleware) into an action (or a |
| 126 | +series of actions) before being sent to the base [`dispatch()`](api/Store.md#dispatchaction) |
| 127 | +function. Async actions may have different types, depending on the middleware you use. They are |
| 128 | +often asynchronous primitives, like a thunk, which are not passed to the reducer immediately, but |
| 129 | +trigger action dispatches once an operation has completed. |
| 130 | + |
| 131 | +Currently the only async middleware published is |
| 132 | +[Thunk middleware](https://github.com/reduxkotlin/redux-kotlin-thunk). Thunk is just any function |
| 133 | +that can be sent to the `dispatch()` function. The Thunk middleware will execute the function. |
| 134 | + |
| 135 | +The design of Redux and its middleware allow creating other Async Action solutions. |
| 136 | + |
| 137 | +## Middleware |
| 138 | + |
| 139 | +```kotlin |
| 140 | +typealias Middleware<State> = (store: Store<State>) -> (next: Dispatcher) -> (action: Any) -> Any |
| 141 | +``` |
| 142 | + |
| 143 | +A middleware is a higher-order function that composes a |
| 144 | +[dispatch function](#dispatching-function) to return a new dispatch function. It often turns |
| 145 | +[async actions](#async-action) into actions. |
| 146 | + |
| 147 | +Middleware is composable using function composition. It is useful for logging actions, performing |
| 148 | +side effects like routing, or turning an asynchronous API call into a series of synchronous actions. |
| 149 | + |
| 150 | +See [`applyMiddleware(...middlewares)`](./api/applyMiddleware.md) for a detailed look at middleware. |
| 151 | + |
| 152 | +## Store |
| 153 | + |
| 154 | +```kotlin |
| 155 | +interface Store<State> { |
| 156 | + val getState: GetState<State> |
| 157 | + var dispatch: Dispatcher |
| 158 | + val subscribe: (StoreSubscriber) -> StoreSubscription |
| 159 | + val replaceReducer: (Reducer<State>) -> Unit |
| 160 | + val state: State |
| 161 | + get() = getState() |
| 162 | +} |
| 163 | +``` |
| 164 | + |
| 165 | +A store is an object that holds the application's state tree. |
| 166 | +There should only be a single store in a Redux app, as the composition happens on the reducer level. |
| 167 | + |
| 168 | +- [`dispatch(action)`](api/Store.md#dispatchaction) is the base dispatch function described above. |
| 169 | +- [`getState()`](api/Store.md#getState) returns the current state of the store. |
| 170 | +- [`subscribe(listener)`](api/Store.md#subscribelistener) registers a function to be called on state |
| 171 | + changes. |
| 172 | +- [`replaceReducer(nextReducer)`](api/Store.md#replacereducernextreducer) can be used to implement |
| 173 | + hot reloading and code splitting. Most likely you won't use it. |
| 174 | + |
| 175 | +See the complete [store API reference](api/Store.md#dispatchaction) for more details. |
| 176 | + |
| 177 | +## Store creator |
| 178 | + |
| 179 | +```kotlin |
| 180 | +// Enhancer is type Any? to avoid a circular dependency of types. |
| 181 | +typealias StoreCreator<State> = ( |
| 182 | + reducer: Reducer<State>, |
| 183 | + initialState: State, |
| 184 | + enhancer: Any? |
| 185 | +) -> Store<State> |
| 186 | +``` |
| 187 | + |
| 188 | +A store creator is a function that creates a Redux store. Like with dispatching function, we must |
| 189 | +distinguish the base store creator, [`createStore(reducer, preloadedState)`](api/createStore.md) |
| 190 | +exported from the Redux package, from store creators that are returned from the store enhancers. |
| 191 | + |
| 192 | +## Store enhancer |
| 193 | + |
| 194 | +```kotlin |
| 195 | +typealias StoreEnhancer<State> = (StoreCreator<State>) -> StoreCreator<State> |
| 196 | +``` |
| 197 | + |
| 198 | +A store enhancer is a higher-order function that composes a store creator to return a new, enhanced |
| 199 | +store creator. This is similar to middleware in that it allows you to alter the store interface in a |
| 200 | +composable way. |
| 201 | + |
| 202 | +Store enhancers are much the same concept as higher-order components in React, which are also |
| 203 | +occasionally called “component enhancers”. |
| 204 | + |
| 205 | +Copies can be easily created and modified without mutating the original store. There is an example |
| 206 | +in |
| 207 | +[`compose`](api/compose.md) documentation demonstrating that. |
| 208 | + |
| 209 | +Most likely you'll never write a store enhancer. Amusingly, the |
| 210 | +[Redux middleware implementation](api/applyMiddleware.md) is itself a store enhancer. |
0 commit comments