This project was bootstrapped with Create React App. I used React, Apollo graphql client and Hooks API to build a page containing a form and a list.
The form adds the 'EUR' price data of a selected cryptocurrency to the list, and cryptocurrency data can be deleted from the list.
Click here to view live demo.
Run this command in the project directory to install all dependencies.
The form accepts text input and suggests cryptocurrency codes matching user input.
This is done by sending a wildcard query to the API that fetches a list of all cryptocurrency codes
available on the featured markets.
I used 'useLazyQuery' in the 'currency-input-form' component to fetch this data.
I wrote a utility function 'FilterCurrencyCodes' which accepts 2 arguments - user input and a list of all
cryptocurrency codes.
It returns a list of filtered currency codes that begin with whatever the user has typed, or an empty array if there is no match found.
This data is used to populate the 'data-list' component which appears just below the cryptocurrency code input element.
Once a valid cryptocurrency code is entered in the input field, another query is sent to the API to fetch the euro price of that cryptocurrency.
This is done within the 'currency-preview' component.
Initially I used 'useLazyQuery' hook for this but refactored the component to call 'useQuery' instead, making it easier to read and maintain.
The project has a global data store containing 'trackedCurrencies' - an array of objects populated from the 'currency-input-form' component.
I implemented shared state using context API and the 'useReducer' hook in 'App.js' with no external libraries.
I implemented persistent state using session storage on line 35 in 'App.js' and in the context definition in 'src/utils/store/index.js'.
This feature persists the app state after page reload, however it is cleared when the page is closed.
I implemented graphql polling with 0.5seconds interval in the 'currency-price' component which primarily displays the price of a cryptocurrency given the 'base symbol' and the 'quote symbol'.
I use this component within the 'currency-list' component to handle fetching multiple queries generated from the 'trackedCurrencies' array.
If a user tries to add a cryptocurrency that is already on the list, it discards the previous entry and adds the new entry at the top of the list.
The 'PreventIdenticalEntries' function can be found in 'src/utils/functions' and it is used in the 'currency-input-form' component.
In the project directory, you can run:
Runs the app in the development mode.
Open http://localhost:3000 to view it in your browser.
The page will reload when you make changes.
You may also see any lint errors in the console.
Launches the test runner in the interactive watch mode.
See the section about running tests for more information.
Builds the app for production to the build
folder.
It correctly bundles React in production mode and optimizes the build for the best performance.
The build is minified and the filenames include the hashes.
Note: this is a one-way operation. Once you eject
, you can't go back!
If you aren't satisfied with the build tool and configuration choices, you can eject
at any time.
Launches a local server on port 5000.
Deploys the 'build' folder to firebase hosting
⚠️ Requires Authentication.
The 'src' folder contains all the files and assets used in the project.
the folders are in the following order;
The components are structured in the following order;
📝 In this section, I documented the thought process behind the pattern and structure of my code in this project.
I wrote simple components that serve as building blocks for more complex systems.
As a result of this modular approach, i created new components for each unique functionality.
The folder structure was also inspired by this consideration.
I dropped comments at the top of each file containing a file description, a reference to where the file was used and the authors name and github link.
This makes it easy to report an issue or track existing issues in the code.
I used suggestive variable and function names to eliminate the need for excessive commenting.
To ensure that the code will not crash unexpectedly if someone else had to maintain it, I implemented type checking on components that accept props.
I also documented my functions properly so that at a glance, another developer working on the project will know what data types to pass and what to expect.
In cases where I worked with unpredictable object properties, I used optional chaining.
Form suggestions, price hint, persistent data and caching with graphql's 'inMemoryCache' all make for a great user experience.
You have come to the end of this project documentation, if you have a question or comment you can reach out. I'd be glad to hear from you!
onepetercollins@gmail.com
Peter Collins