asg2-react
Name: Rudine Surya Hartanto
website url: https://ess-ewd-react.firebaseapp.com/
server: https://github.com/rudinesurya/mern-web-asg2
client: https://github.com/rudinesurya/ess-ewd-asg2-react
Table of Contents
Overview
App Concept
This is an app for quick contract job, similar to the likes of Meetup. It has some form of social networking feature, eg. the ability to view user's profile and chat
Objectives
- For the host: Enable quick solution for finding adhoc work done.
- For the jobseeker: Enable checking out the job details and payment before joining.
Features
- CRUD operation
- List Jobs (Sorting, Filtering)
- View & Edit Job Detail
- Chat system in the job page
- Login / Register
- View other user's profile
- Edit self user profile
- Join / Leave Job
- Custom Notifications
- Google Maps and Autocomplete
- Redux state management
Setup Requirements
Installation
- npm install
- npm start
Configuration
change the axios.defaults.baseURL (in index.jsx) to your own endpoint. Also make sure that the port of the server and this app are not the same.
warning: certain pages can be loading forever if the user is not authenticated. To avoid this, you have to login before accessing any pages except the homepage.
App Component Design
Only root components are made to be stateful. ie, they will have dependencies to 3rd party web api and be passing props down the tree to the stateless children components.
UI Design
- Using semantic-ui for its simple and clean ui theme.
- Public / Private views: certain ui elements will be hidden when user are not authenticated.
Routing
route | view |
---|---|
/jobs | the job dashboard (homepage) |
/job/:id | detail view of a particular job (:id) |
/login | login page |
/register | registration page |
/updateJob/:id | job creation form |
/createJob | job creation form |
/profile/:id | user profile page |
/editProfile/:id | user profile edit form |
/error | error page |
Protected Routing
- /updateJob/:id
- /createJob
- /editProfile
Error Handling
- Trying to access pages with invalid url or job/user id which does not exist will force the user to be redirected to an error page.
- Unauthenticated user trying to access protected routes which require authentication, such as job creation or user profile editing page will be redirected to home page.
Integration with Backend Api
Axios
Axios is a promise based HTTP client for making HTTP requests from a browser to any web server.
axios.get(‘/url’,{data:’data’}).then((res)=>{
//on success
}).catch((error)=>{
//on error
});
axios.post(‘/url’,{data:’data’}).then((res)=>{
//on success
}).catch((error)=>{
//on error
});
Loading the data during ComponentDidMount
When the components loads, this will trigger this lifecycle to fire the loadJobs() action.
componentDidMount() {
const { loadJobs } = this.props;
loadJobs();
}
Sending the data to the reducer
The rest call inside will return a json output, which will be sent as payload to the reducer.
export const loadJobs = () => async (dispatch, getState) => {
try {
dispatch({ type: JOB_START_REQUEST });
const res = await axios.get('/api/jobs');
dispatch({
type: LOAD_JOBS,
payload: res.data,
});
} catch (err) {
dispatch({
type: JOB_ERROR,
payload: err.response.data,
});
}
};
The reducer store the payload in the state
The reducer will receive the payload and update its state.
const loadJobs = (state, action) => ({
...state,
loading: false,
jobs: action.payload,
error: {},
});
Mapping the data from redux store to props
In the component, we can access the redux store by connecting this method. And then we can map this data to props for the component to use.
const mapStateToProps = state => ({
job: state.job,
});
Getting the data from props
After the mapping, we are free to use the data.
render() {
const { job } = this.props;
if (job.loading) return (<Spinner />);
return (
<JobList jobs={job.jobs} />
);
}
LiveData
The Pusher enables the client to listen for changes in the server. React to real-time date changes.
// The react app will listen to this channel, for simplicity, the page will reload when a change stream is observed.
const channel = pusher.subscribe(jobId);
channel.bind('postComment', (data)=> {
dispatch(loadJob(jobId));
});
channel.bind('deleteComment', (data)=> {
dispatch(loadJob(jobId));
});
Authentication
Authentication is handled by our backend service using json web token. The client app just need to store the token in localstorage to enable the web app to keep the user logged in during page refresh. This token will be passed to the header of the rest api requests for accessing restricted resources. The code below enables all axios calls to be set with the authenticated token. If it exists.
const setAuthToken = (token) => {
if (token) {
axios.defaults.headers.common.Authorization = `Bearer ${token}`;
} else {
delete axios.defaults.headers.common.Authorization;
}
};
Server Side Validations
All the forms in the app uses server side validations.
When the form gets submitted, it will call a rest call to the endpoint, which will then return the result or the error. The error will then be used to render the error messages on the form.
Deployment
Deployed to firebase
Third Party Libraries
- google-map
- react-places-autocomplete
- prop-types
- react-toastify
- react-datepicker
- react-redux
- redux-form
- redux-thunk
- revalidate
- semantic-ui-react
- date-format
- react-semantic-redux-form
- redux-devtools
References
https://react.semantic-ui.com/
https://redux.js.org/introduction/getting-started
https://alligator.io/redux/redux-thunk/
https://redux-form.com/8.1.0/docs/gettingstarted.md/
https://github.com/jfairbank/revalidate#readme
https://redux-form.com/8.1.0/examples/react-widgets/