ui-workshop-102 v1.0.0
ui-workshop-102
Setup
Cox Automotive NPM Artifactory Auth set up can be done by using the artifactory-npm-auth.js
script in the LocalSetup Don't Panic readme.
Needed tools
- An IDE (VS Code, Intellij IDEA, Sublime, vim, maybe Emacs :smile:)
- node.js - interpreter used for development tools
- nvm - node.js version manager
- npm - package manager / project manager tool
Use the following command to determine which versions you have installed on your machine
node --version && npm --version
This project was built with node.js v18.14.0
and npm 9.3.1
To change the installed version of node and npm use the following commands
- node -
nvm install
- nvm uses the .nvmrc file to pull the correct version
How to run
Use the simple command below to get the webpack dev server running
npm start
Navigate to http://localhost:8080. You should see a menu application.
Assignement
With larger applications state manipulation can become difficult to manage. Application state needs to have a single source of truth and be predictable. Adding in external data sources, ex. back end services
Purpose: Learn basic data fetching paradigm, the React component lifecycle, and Redux state.
Information
This application is a restaurant food ordering application. It allows a person to select menu items, quantity, and calculates the cost of the full order. The list of menu items and their data structure are predefined as the following.
{
name,
description,
cost per unit,
id
}
Steps
- Currently the menu items are hard coded. A more extensible approach would be to have the menu provided by a centralized service, a single source of truth. This service is currently in place at the
/menu
endpoint. (For this assignment the webpack devServer is mocking this out, see webpack.dev.js) In theutils.js
file there is a very basic get function that can be used to fetch data from a service. It's signature takes an url and a callBack. The call back will be called with the response JSON when the request returns. React component lifecycle is a powerful part of the React framework. For this assignment we will need to utilize thecomponentDidMount
method. The best approach to get the menu from the service and pass the response to the required components would be to put the get call at the top level App component and have the callBack update component state, (HINT:this.setState({menu: json})
). The manipulation of the items in the order, adding and removing items, through component state by passing functions to child components can get very clunky. This may not be visible in this assignment but imagine having a large tree of components with parents and children where a far ancestor of the top most component needs to change application state. A helper function would need to be passed down through the component hierarchy the the ancestor. It would be awesome if we had a way of decoupling shared state from components. This is where Redux fits in. Redux is "A Predictable State Container for JS Apps".
Add redux packages to the application.
npm install redux react-redux redux-immutable immutable
- redux - core redux utilities
- react-redux - react integration with redux
- redux-immutable - used to create an equivalent function of Redux combineReducers that works with Immutable.js state
- immutable - is a peer dependency for redux-immutable
Initialize application Redux state.
- Create a
store.js
file. - By using Redux's createStore function create a state store. The createStore function is where we will register our reducers in the future. Export the created store (HINT:
export default store;
). - Import the store from
store.js
and Provider fromreact-redux
in theindex.jsx
file. - Wrap the App component with the a Redux Provider component and add the store as attribute of the Provider
- Create a
Create actions and reducers for order manipulation.
- Create a
order.js
file. - Create three functions addAction, deleteAction, and reducer with the following signatures
- addAction -
const addAction = (id, count) => { return {type: ADD, ... }; };
(HINT: Redux actions return an object with information about the desired state update.) - deleteAction -
const deleteAction = (id) => { return {type: DELETE, ... }; };
- reducer -
const reducer = (state = initialState, action) => { ... };
(HINT: A Redux reducer takes current state and returns a new version of state with the update from the passed in action, ex.switch
on the type of the action.initialState
will also need to be initialized as a default parameter for the reducer)
- addAction -
- Export all three functions so they can be used in other parts of the application
- In store.js import the reducer and add it to the list of reducers being passed to the Redux createStore function. To do this with immutable state wrap the list of reducers with redux-immutable's combineReducers function. (HINT:
const store = createStore(combineReducers(order: reducer));
)
- Create a
Wire Redux actions to the application. This should be done in each child component (Menu and Order). Redux actions get executed through dispatch calls. In order to get access to the Redux dispatch function we need to wrap our components with state manipulation, Redux connect function. With this change there is no need to pass updateFn to the children or maintain the menu order in App's component state. Sample changes for the Order component are below. (NOTE: The Menu component also needs to be updated.)
... render() { const { order, deleteItem, } = this.props; ... } ... Order.propTypes = { menu: PropTypes.shape({ items: PropTypes.arrayOf(PropTypes.shape({})), }), order: PropTypes.shape({}), deleteItem: PropTypes.func.isRequired, }; const mapStateToProps = state => ({ order: state.get('order'), }); const mapActionsToState = dispatch => ({ deleteItem: (id) => dispatch(deleteAction(id)), }); export default connect(mapStateToProps, mapActionsToState)(Order);
Breathe a sigh of relief, you got through that massive mind dump from the author. Oh, also single source of truth, state is read-only, changes are made with pure functions.
BONUS Assignment
Now that you know how to use Redux to manage application state is it possible to use Redux to maintain what gets returned from the data service? Yes!
Purpose: Reinforce what was learned in the previous assignment.
- Create a Redux action for the menu data returned from the data source.
- Create a Redux reducer for updating Redux state.
- Wire in the action and reducer to all three components, App, Menu, Order.
- Have an awesome day!
Over Achievers Assignment
Make the application calculate tax for a given state. There just happens to be an endpoint from the data service that provides a sales tax per state mapping, /salesTaxByState
.
Purpose: More reinforcement of fetching data and component state manipulation. NOTE: This is meant to be very open ended.
- Add a drop down selector from
react-select
(HINT:npm install react-select
andimport Select from 'react-select';
) - Wire a fetch call in the application to request data from the data service.
- Manage state for the drop down and use it's state to calculate the tax for order.
- Feel confident that you are multi state sales tax complaint, sort of. :smile:
1 year ago