Coder Social home page Coder Social logo

goalsetter's Introduction

Goalsetter Web App

Built this while learning about React and the MERN stack

Table of contents

Overview

Screenshot

Links

My process

Built with

  • React - JS library
  • Redux.js - State management
  • Redux Toolkit - Toolset for Redux
  • Express.js - Web-framework for Node.js
  • Mongoose - MongoDB object modeling for Node.js
  • JWT - JSON Web Tokens
  • Semantic HTML5 markup
  • Mobile-first workflow
  • Flexbox

What I learned

Developing this application with help from Traversy media helped me to learn so much about the MERN stack, REST APIs, MongoDB, state management with Redux, functional React components, and deployment with Heroku.

I learned about using Axios to make HTTP requests from the frontend

const createGoal = async (goalData, token) => {
  const config = {
    headers: {
      Authorization: `Bearer ${token}`,
    },
  };

  const response = await axios.post(API_URL, goalData, config);

  return response.data;
};

Learned about thunk functions to handle asynchronous requests

// Get user goals
export const getGoals = createAsyncThunk(
  'goals/getAll',
  async (_, thunkAPI) => {
    try {
      const token = thunkAPI.getState().auth.user.token;
      return await goalService.getGoals(token);
    } catch (error) {
      const message =
        (error.response &&
          error.response.data &&
          error.response.data.message) ||
        error.message ||
        error.toString();
      return thunkAPI.rejectWithValue(message);
    }
  }
);

And using slices with extra reducers to update the global state

export const goalSlice = createSlice({
    name: 'goal',
    initialState,
    reducers: {
        reset: (state) => initialState,
    },
    extraReducers: (builder) => {
        builder
            .addCase(createGoal.pending, (state) => {
                state.isLoading = true;
            })
            .addCase(createGoal.fulfilled, (state, action) => {
                state.isLoading = false;
                state.isSuccess = true;
                state.goals.push(action.payload.goal);
            })
            .addCase(createGoal.rejected, (state, action) => {
                state.isLoading = false;
                state.isError = true;
                state.message = action.payload;
            })

I also learned a lot about creating a backend, modeling your data, and setting up routes for the API

Built schemas using mongoose

const userSchema = mongoose.Schema(
  {
    name: {
      type: String,
      required: [true, 'Please add a name'],
    },
    email: {
      type: String,
      required: [true, 'Please add an email'],
      unique: true,
    },
    password: {
      type: String,
      required: [true, 'Please add a password'],
    },
  },
  {
    timestamps: true,
  }
);

Used express router to handle requests to API endpoints

router.post('/', registerUser);
router.post('/login', loginUser);
router.get('/me', protect, getMe);

And built controllers for each endpoint

// @desc    Register new user
// @route   POST /api/users
// @access  Public
const registerUser = asyncHandler(async (req, res) => {
  const { name, email, password } = req.body;

  if (!name || !email || !password) {
    res.status(400);
    throw new Error('Please add all fields');
  }

  // Check if user exists in db
  const userExists = await User.findOne({ email });

  if (userExists) {
    res.status(400);
    throw new Error('User already exists');
  }

  // Hash password
  const salt = await bcrypt.genSalt(10);
  const hashedPassword = await bcrypt.hash(password, salt);

  // Create user in db
  const user = await User.create({ name, email, password: hashedPassword });

  if (user) {
    res.status(201).json({
      _id: user.id,
      name: user.name,
      email: user.email,
      token: generateToken(user._id),
    });
  } else {
    res.status(400);
    throw new Error('Invalid user data');
  }
});

I enjoyed learning about middleware for overwriting the deafult error handler, but more importantly, to handle authentication and authorization for protected routes (JSON Web Tokens)

const protect = asyncHandler(async (req, res, next) => {
  let token;

  if (
    req.headers.authorization &&
    req.headers.authorization.startsWith('Bearer')
  ) {
    try {
      // Get token from header
      token = req.headers.authorization.split(' ')[1];

      // Verify token
      const decoded = jwt.verify(token, process.env.JWT_SECRET);

      // Get user from token
      req.user = await User.findById(decoded.id).select('-password');

      next();
    } catch (error) {
      console.log(error);
      res.status(401);
      throw new Error('Not authorized');
    }
  }

  if (!token) {
    res.status(401);
    throw new Error('Not Authorized, no token');
  }
});

Continued development

Moving forward, I am very excited to start using this stack and development approach for future projects of all sizes. I realize I have much to learn, but I have a much better understanding of the process and architecture. I want to continue focusing on the MVC structure, Express as a backend framework, React and all the many things it has to offer, and different ways of managing state.

I found Redux to be overwhelming and overly complicated. I will continue practicing using the technology, and also begin exploring alternatives such as Context API.

Useful resources

  • Traversy Media - Brad is hands down the best teacher for all things web dev. I have learned so much because of this man. He deserves so much credit!
  • React Docs - The documentation for React is very well designed and maintained. I highly recommend coming here first for all questions regarding the library.

Author

Acknowledgments

A huge thanks to Brad Traversy and his YouTube channel. I would not be where I am in my journey of learning to be a developer if it wasn't for him and his content. Thanks!

goalsetter's People

Contributors

jeramiahgcoffey avatar

Stargazers

Roman avatar Tom Connors avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.