-
Notifications
You must be signed in to change notification settings - Fork 0
Redux Global State
The Redux global state is the store for application state for QueueMeIn, utilizing the redux, react-redux, and redux-thunk npm packages. It is composed of asynchronous actions, reducers for updating state, the store itself, and the components it is incorporated into. Please note that the process of refactoring props into global state is in progress, and this page will be updated as more state is added to Redux.
With redux-thunk, actions become functions that return asynchronous callback functions. When actions are called within a React component, the redux-thunk middleware then calls the actual callback functions and uses the Redux dispatch function to dispatch an action. Actions allow the state-updating logic to be refactored away from the React logic, and can have side effects unlike reducers. You can read more about thunks here.
For the most part, because we do not have a formal backend in QMI and the majority of state-updating backend logic is centered around rxjs hooks rather than asynchronous API calls, the actions will be synchronous. To leave the door open to future asynchronous logic, we still use thunks.
In QueueMeIn, actions have types and data, with types stored in /src/redux/actions/Types.ts as exported constants. Each component of the top level global state has a set of actions, somewhat like api endpoints but for front-end state. Currently, the only component of the global state is user and authentication information, with the actions under /src/redux/actions/auth.ts. There are currently two actions, updateUser and updateAuthStatus.
Description: Takes in a FireUser, and dispatches an UPDATE_USER action to the Redux store.
Parameters: The user parameter of type FireUser | undefined.
Returns: A callback function that dispatches the requisite action.
Runtime: O(1)
Description: Takes in an authState, and dispatches an UPDATE_AUTH action to the Redux store.
Parameters: A single authState boolean that describes whether the user is currently authenticated.
Returns: A callback function that dispatches the requisite action.
Runtime: O(1)
Reducers take in actions from the dispatch function and update the state according to the type and the payload. There is a single reducer for the entire store, segmented into each portion of state. Similar to actions, each component of the top level global state (currently only auth) has a reducer, and each of them are combined with the combineReducers Redux function to create the single global reducer. Each reducer (the subcomponents of the single overall reducer) defines an initial state for the portion of the global state it is responsible for updating and maintaining. A reducer is, at its core, a function that takes in a state and action and outputs a state. The auth reducer is partitioned by the action types.
Description: Takes in a redux state and an action, and updates the state according to the action type for UPDATE_USER and UPDATE_AUTH actions. Parameters: The state parameter of type AuthState, with the default state being the defined initialState for the auth subcomponent of the global state. Returns: The updated state of type AuthState Runtime: For this specific reducer, O(n) where n is the size of the state. This is true for most reducers because they tend to use the spread operator to fill the state that is not modified.
State and actions are passed to React components via the react-redux package, which passes actions and pieces of state to components via props. The react-redux package uses the connect function to create wrapper React components around the actual components that pass the state and dispatches down as props.
Description: Has four optional parameters that allow the user to specify what Redux data is passed to a component, and returns a wrapper React component on top of the original component.
Parameters: connect has four optional parameters, described in detail here. The ones we use are mapStateToProps, and mapDispatchToProps.
- MapStateToProps is a function of type (state, ownProps?) => Object that takes in the global Redux state, and returns the object that is passed to the props with the spread operator. It is used to specify the exact pieces of the state need for the given component.
- mapDispatchToProps can also be a function, but preferably we use it as an Object that defines the actions that are used in the component. If actions are called separately, they simply return callbacks which are never themselves called and thus dispatch is never used. mapDispatchToProps incorporates the thunk middleware that makes the asynchronous actions useful. So if I wanted to use the updateUser action within a specific component, I would import it at the top, pass it in the mapDispatchToProps object to connect, and then call props.updateUser. The function also takes a React component as the final parameter, in the form connect(mapStateToProps, mapDispatchToProps)(React Component). It works with functional and class-based components, because it simply returns a wrapper around them.
Returns: A wrapper React component that incorporates and passes the global Redux state to the subcomponent passed to connect.
Runtime: Should be O(1) because only pieces of the state are touched and actions are passed directly, but depends on the underlying react-redux implementation.