Skip to main content

React

Welcome, here is what you will be doing in the next two weeks:

  • Brush up on your React skills and read through the materials provided by DECODE.
  • Develop an app which will be some type of a clone of Tumblr. Tumblr documentation: Tumblr
  • As you progress, make a new commit every time you finish implementing something (so we can track your progress and give you some useful feedback as you progress). For example:
    • When you finish setting up your project, make a new commit.
    • When you finish with the main screen, make a new commit.
    • ... and so on
  • Use Git Flow.

Suggested "commit" points are marked as little code blocks like this -> Commit Point.

This way, somebody can take a look and monitor your progress on your feature branch.

Each task is started on its own feature branch.

  • After the task is done and when you see a Merge Request annotation, make a merge request from your feature branch to the master branch for somebody to take a final look. Assign it to someone who is assigned to you as your onboarding buddy.

  • Please add comments or suggestions to this document using the "add comment" feature visible at the right side of the document. Add a comment or suggestion for everything that is not explained enough or is misleading to you.

  • You should have enough time to finish this project in 10 days, so take it slowly to learn as much as you can.

Before you start

  • Get familiar with official React docs. We're using it for creating components.
  • We're going to keep it simple and use a webpack boilerplate for the project setup. If you want to explore more, check out the webpack documentation.
  • If you want to know more about the webpack boilerplate, you can check out the GitHub repository.
  • If you're not familiar with TypeScript, you should check out their official documentation and find out why it's so popular.
  • If you're unfamiliar or have never worked with Git, read up on the basic commands. Also, some of us use SourceTree GUI, which provides a nice user interface for all Git-related actions. Check out Git - Book Sourcetree | Free Git GUI for Mac and Windows Git-FER.
  • In this onboarding, we're using Yarn as the package manager, but of course, if you want to use npm, that's also fine. Here are the yarn docs if you want more info.
  • For styling our app, we're going to use styled components, so you can check out their official docs.
  • For data, we will be using the Tumblr API, so you can also check out the docs. Since we're using JavaScript in this onboarding, we've used a library called tumblr.js for easier data fetching.
  • For API data management we’re going to be using React Query and the official docs for that is on TanStack Query

Setting up the boilerplate

As your first task, you'll be bootstrapping your boilerplate. Clone the repo (React Webpack TypeScript Starter) and get up and running. Go through the repo files, webpack config, and try as a side task to refactor index.html.ejs file to just index.html with the hot reload.

Setting up styled components

Next, we're going to install the styled-components. Use the documentation to see how to bootstrap it with your project. Also, if needed, try and find out how to inject the library into your webpack config.

After you've installed the library, you will set up the folder structure. We're going to give you an example of how we structured the project when using SCSS so you can use it for your styled components.

Folder structure in src

 scss
├── base
│   ├── _colors.scss
│   ├── _index.scss
│   └── _typography.scss
└── main.scss

The goal is to change the color of h1 to gray and test that our installed packages are working well and that babel compiles it correctly. Add the following code to files respectively:

// colors.scss
$gray: #888ea7;

// typography.scss
h1 {
color: $gray;
}

// index.scss
@import "colors";
@import "typography";

// main.sccs
@import "base/index";

Lastly we’re going to import our main.scss styling file in index.tsx

So the goal here of setting up the styled components is to refactor the boilerplate, bootstrap it with styled-components lib and create a folder structure lead by the given example. You can make your few custom components and refactor the App.tsx file with your newly created components.

1st Commit point

We’ve finished the part of setting up our project. Now you can commit your changes and push it as an initial commit to your onboarding repo. If you have found a bug or of course a better way to implement something please share your knowledge with us. We will gladly accept your suggestions that benefit this onboarding!

Add pages to your project

Start a new branch named feature/app-base . The goal of this task is to use your imagination and create styling and functionality for your app. Since you are using React with Typescript use your skills or help yourself going through documentation.

First part

We are going to be super simple. We will create only one initial page on which we will display liked photo posts from tumblr. In src create pages folder and add PostsPage. If you want to play around and create more pages use react-router-dom to navigate through your pages.

yarn add react-router-dom

For page styling in scss also create pages folder and follow the file structure as previous example. Fell free to add any other details to styling if you want (custom fonts, svgs, logos, animations, etc..).

Below is file structure example of described task for your reference:

src
├── index.tsx
├── pages
│ ├── PostDetailPage.tsx
│ └── PostsPage.tsx
└── scss
├── base
│ ├── _colors.scss
│ ├── _index.scss
│ └── _typography.scss
├── main.scss
└── pages
├── _index.scss
├── _post-detail-page.scss
└── _posts-page.scss

Second part

We will need real data from the tumblr API so we can create our posts list and single post. First we’ll need to register on tumblr API:

  1. Create a tumblr account and verify your email

  2. Go to app registration

  3. Once the app is registered click on it and copy OAuth consumer key and OAuth consumer secret to tumblr console.

When successful the console will show a javascript method example for creating a tumblr client with whom we will fetch the data from the api. We are lucky that for javascript there exists a lib which we will need to install. The lib is called tumbrl.js → package.

 yarn add tumblr.js

It’s totally up to you on how you want to fetch the data from the tumblr service. If you feel you need redux you can. If you want to use Reacts own Context API or for example react-query you are free to do. For your reference and guide we will provide a simple service example that we’ve used here as a solution.

We’ve created a services folder in src named TumblrService.ts which we will use for data fetching.

const tumblr = require("tumblr.js");

export default class TumblrService {
private client: any;

constructor() {
this.client = tumblr.createClient({
credentials: {
consumer_key: "<your_consumer_key>",
consumer_secret: "<your_consumer_secret>",
token: "<your_token>",
token_secret: "<your_token_secret>",
},
returnPromises: true,
});
}

async getUserInfo() {
try {
const response = await this.client.userInfo();

return response.user;
} catch (error) {
console.error(error);
}
}

async getUserLikes() {
try {
const response = await this.client.userLikes();

return response;
} catch (error) {
console.error(error);
}
}
}

Since we’re going simple we’re fetching only user info and user posts that were liked. So if you don’t have any posts liked on your account go on tumblr and click on few. We’re only going to focus on photos so please choose posts that are photos only. If you want to do extra fun stuff create your initial page that supports all types of posts (videos, gifs, …). Try to make it when clicked on liked post, its details must open in a popup window of the desktop app.

2nd Commit point

When you’ve finished all of the work create a pull request for base of your app. Assign the PR to someone who’s your buddy on our onboarding process.

Estimate 2 days

Blog statistics page

In this part we’re going to make a page that represents a blog statistics. Since now you’ve already went through the tumblr API try and see which of the methods you can use to make a statistics page in your app.

To our pages folder structure we’re going to be adding a new BlogStatisticsPage.tsx

src
├── index.tsx
├── pages
│ ├── PostDetailPage.tsx
│ ├── BlogStatisticsPage.tsx
│ └── PostsPage.tsx
└── scss
├── base
│ ├── _colors.scss
│ ├── _index.scss
│ └── _typography.scss
├── main.scss
└── pages
├── _index.scss
├── _post-detail-page.scss
└── _posts-page.scss

You can open up a new branch called feature/blog-statistics and start with your development. Since you have your react-query library installed you’re going to combine that library with data fetching. It would be good if you install axios for data fetching.

As a suggestion you can maybe add some additional folders to your project. You can make an api folder to your project to put your axios request methods. Also, you can add services folder where you can put additional services if needed.

For example for easier axios usage you can make a service called api.ts that will handle request errors and where you can set up your axios interceptors.

export default class ApiService {
instance: any;

constructor() {
axios.defaults.withCredentials = true;

this.instance = axios.create({
baseURL: process.env.REACT_APP_API_SERVICE,
});

this.setRequestInterceptors();
this.setResponseInterceptors();
}

setRequestInterceptors() {
this.instance.interceptors.request.use(
(config: any) => {
return config;
},
(error: any) => {
return Promise.reject(error);
}
);
}

setResponseInterceptors() {
this.instance.interceptors.response.use(
(response: AxiosResponse) => {
return {
data: response.data,
status: response.status,
};
},
(error: any) => {
return new Promise((resolve, reject) => {
if (error instanceof axios.Cancel) {
return;
}

let errorMessages: any = {};

enum STATUS {
PAGE_NOT_FOUND = 404,
UNAUTHORIZED = 401,
BAD_REQUEST = 400,
SERVER_ERROR = 500,
}

const statusCode = error && error.response.status;

if (statusCode >= 400 && statusCode < 500) {
switch (statusCode) {
case STATUS.PAGE_NOT_FOUND:
window.location.href = NOT_FOUND_PAGE;
break;

case STATUS.UNAUTHORIZED:
window.location.href = LOGIN_PAGE;
errorMessages = error.response.data;
break;

case STATUS.BAD_REQUEST:
errorMessages = error.response.data;
break;

default:
break;
}
} else if (statusCode >= 500 || statusCode === undefined) {
switch (statusCode) {
case STATUS.SERVER_ERROR:
window.location.href = ERROR_PAGE;
break;

default:
break;
}
}

reject({
error: error.response.data.error,
errorMessages,
statusCode: error.response.status,
});
});
}
);
}

get({ resource, params }: GetParams) {
return this.instance.get(resource, params);
}

post({ resource, data }: PostParams) {
return this.instance.post(resource, data);
}

patch({ resource, data }: PatchParams) {
return this.instance.patch(resource, data);
}

put({ resource, data }: PutParams) {
return this.instance.put(resource, data);
}

delete({ resource }: DeleteParams) {
return this.instance.delete(resource);
}
}

interface GetParams {
resource: string;
params: object;
}

interface PostParams {
resource: string;
data: object;
}

interface PatchParams {
resource: string;
data: object;
}

interface PutParams {
resource: string;
data: object;
}

interface DeleteParams {
resource: string;
}

This is just an example that can lead you through your services. You don’t have any authentications so some error handling might not be needed in your services.

NOTE:

Also, in this it would be nice if you could spend a little more time on styling. The styling of the statistics and the layout is all up to your imagination. Maybe it would be a great idea to get some inspiration from professionals? You can check out Dribbble to get some inspiration.

Finally, the end goal of this feature branch is to add as much meat to your project bone structure. So go all in with your services, data fetching, context business logic or UI business logic and app styling.

🎉 🎉 🎉 🎉 🎉

3rd Commit point

As always when you’ve finished all of the work create a pull request for your feature branch and call in your buddy.

Estimate 2 days