Answer the following questions considering the learning outcomes for
Make sure to record evidence of your processes. You can use code snippets, screenshots or any other material to support your answers.
Do not fill in the feedback section. The Founders and Coders team will update this with feedback on your progress.
[Learning outcomes...]
[your evidence here]
2. Show an example of some of the learning outcomes you have struggled with and/or would like to re-visit.
[Learning outcome...]
[your evidence here]
-
I implemented global state management with React Context to manage the shopping cart state across components (
ProductCard
,ShopCart
,Header
). UsinguseReducer
, I centralised cart actions, including adding, removing, and updating quantities.import { createContext, useContext, useReducer } from "react"; const CartContext = createContext({ state: initialState, dispatch: () => null }); const cartReducer = (state, action) => { switch (action.type) { case "ADD_TO_CART": // logic to add item case "DECREASE_QUANTITY": // logic to decrease item quantity default: return state; } }; export const CartProvider = ({ children }) => { const [state, dispatch] = useReducer(cartReducer, initialState); return ( <CartContext.Provider value={{ state, dispatch }}> {children} </CartContext.Provider> ); };
-
I created a custom hook,
useCartContext
, to simplify accessing cart state and actions across components.export const useCartContext = () => { const context = useContext(CartContext); if (!context) { throw new Error("useCartContext must be used within a CartProvider"); } return context; };
-
I refactored several components, and it was a long job, to ensure TypeScript type safety. Below an example of how I defined interfaces for props and state to eliminate implicit
any
types, reducing potential runtime errors.interface CartItem { id: string; name: string; price: number; quantity: number; } interface CartState { items: CartItem[]; totalAmount: number; } const initialState: CartState = { items: [], totalAmount: 0, };
-
Implemented Cart Summary with Dynamic Shipping Options: Based on feedback from Max, I updated the
CartSummary
component to fetch shipping options from the database. Now users can select a preferred option, which then adjusts the delivery charge and total price.useEffect(() => { fetch('http://localhost:3000/shipping-options') .then(response => response.json()) .then(data => setShippingOptions(data)) .catch(error => console.error('Error:', error)); }, []);
-
I initially struggled to decide between
useState
anduseReducer
for managing cart state. I eventually choseuseReducer
to handle the cart's complex logic.const cartReducer = (state, action) => { switch (action.type) { case "ADD_TO_CART": // logic for adding item default: return state; } };
-
Encountered TypeScript errors when passing complex objects, such as social media icons, as props in components. Initially defined
name
as astring
, which caused conflicts when JSX elements were passed. Adjustedname
toReact.ReactNode
, which resolved the issue.-
Code Example:
const socialLinks = [ { name: <FaFacebookF />, url: "https://www.facebook.com" }, { name: <FaTwitter />, url: "https://www.twitter.com" }, ];
-
-
Automating Frontend Deployment: Configured an automated deployment pipeline using GitHub Actions and AWS CDK for the frontend. The pipeline builds, tests, and deploys the application to an AWS S3 bucket. The CI/CD process has made deployments quicker and more reliable.
name: Frontend Deployment on: push: branches: - main jobs: deploy: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v2 - name: Install dependencies run: npm install - name: Build frontend run: npm run build - name: Deploy to S3 env: AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} run: aws s3 sync ./dist s3://my-bucket-name --delete
-
** BackEnd Deployment**: Successfully deployed the backend using EC2 and configured
pm2
for process management.const app = new cdk.App(); new Pro04BackendCdkStack(app, 'Pro04CdkStack', { env: { account: 'account-id', region: 'eu-west-2' } }); app.synth();
-
I realised that TypeScript configuration in
tsconfig.json
needed adjustments. This issue was evident by GitHub Actions not recognising type declarations during deployment, which required adding steps to ensure TypeScript compiles correctly in the CI environment. -
Had an
UPDATE_ROLLBACK_FAILED
error during deployment, which prevented the CloudFormation stack from updating. I decided to manually deleting the stack, and retrying deployment, but I failed to do so and gave up.
-
Faced TypeScript compilation errors in the CI pipeline due to missing module declarations, specifically
aws-cdk-lib
. This required adjusting TypeScript settings and ensuring that all necessary dependencies were installed in the CI environment. -
I mistakenly ran the backend on the incorrect computer, leading to confusion and deployment delays.
[Course Facilitator name]
Alexander
[What went well]
Excellent implementation of global state management using Context and useReducer with proper TypeScript typing. Good progression from basic cart functionality to more complex features like dynamic shipping options. Strong CI/CD setup with GitHub Actions.
[Even better if]
Document your CloudFormation stack error and resolution attempts in more detail - the "gave up" approach doesn't help track what specifically went wrong for future reference.