What should have a company to work on in?

Yeah!!! It should be your first question when you started reading this post series πŸ˜„, it means what should have a company to love me.

Let me start telling that I have just rejected tons of job positions, as I said before I don’t choose a job only by the salary, it should be the last weight into your decision πŸ’». I mean, I prefer to have a really enjoyable working environment than have an awful one, it means feeling exactly you want everyday.

There are a lot of companies in the world with different background and opportunities πŸ›, but unfortunately I have heart a lot:

I will pay you whatever you want if you work on my company 😞

or maybe, the typical phrase:

We want the best one β–².



Nevertheless, what does it mean πŸ˜…?

It means exactly that they will always take into account your knowledge, they don’t care about your experience, background, mindset, they only want you to put the fire away 😏. They don’t care about you, you are practically judge of your knowledge, maybe you have less experience than another candidate, but you have more practical use cases and you are able to learn in half time, but it doesn’t care, they are looking at the present.

If you get a job there, you will only be asked for solutions 🧐, and after each sprint you will get a pat on the back 😞. Mainly you are working such a robot, you get requirements and are asked for a solution. I think it’s really bored, I’m sure you will get out ASAP.

I hate this type of companies where your job is the most important thing, otherwise, there are some companies (unfortunately lesser 😁) that really appreciate your background, experience and the most important thing, your mindset, yeah, I know, the only needed thing is to have wanted. You are able to learn whatever you need, it only takes some time, these types of company allow you to grow your professional career really faster that another ones.

I mean to appreciate when a company is asking about your mindset, I assure you that you will get a really confortable working environment where you will be able to learn everyday, πŸ˜‡ these are the keys I’m looking for when I receive a new job opportunity. I always keep in mind this phrase:

If you are the best you will get paid as one.

That’s all, it’s my opinion about new job positions, if you like this post please share with your friends and give us a feedback about it. We really appreciate it.


Source link

React Componenets in Markdown articles

As I decided to create my blog I choose Next.js as my framework of choice, as a backend I use markdown files stored in a git repo.

To render my files I use React Markdown. It’s an awesome component that can render markdown files without any config.

After a few posts, I figured out that I need some custom components rendered with my posts. One was for images, to make them zoomable for phones and the second one was a syntax highlighter for code snippets.

React has a huge amount of components that can help us with both of these. I decided to use react-zoom-pan-pinch for image zoom and react-syntax-highlighter for syntax highlight.

Ok. I have my components, not how to render them from our markdown files. Fortunately, React Markdown has us covered. It allows us to do a custom rendering of some tags.

We can do something like this:

import ReactMarkdown from 'react-markdown';
import  Prism as SyntaxHighlighter  from "react-syntax-highlighter";
import  materialDark  from "react-syntax-highlighter/dist/cjs/styles/prism";
import  TransformWrapper, TransformComponent  from "react-zoom-pan-pinch";

<ReactMarkdown
    components={{
        p: ( node, children ) => 
            if (node.children[0].tagName === "img") 
                const image = node.children[0];
                return (
                    <TransformWrapper>
                        <TransformComponent>
                            <img
                                alt=image.properties.alt
                                src=`$image.properties.src`
                            />
                        </TransformComponent>
                    </TransformWrapper>
                );
            
            // Return default child if it's not an image
            return <p>children</p>;
        ,
        code( className, children ) 
            // Removing "language-" because React-Markdown already added "language-"
            let language = "";
            if (className) 
                language = className.replace("language-", "");
            
            return (
                <SyntaxHighlighter
                    style=materialDark
                    language=language
                    children=children[0]
                />
            );
        ,
    }}
>
    postData.contentMarkdown
</ReactMarkdown>

For images, we must hook into

tag, as ReactMarkdown is wrapping images in paragraphs. So with a simple if we decide if the first child of the paragraph is an image. If so we replace the whole thing.

For code, we are just replacing the whole code tag.

If you like this article you can follow me on Twitter.




Source link

Understanding how API routes work in Next.js

Next.js makes it really simple for developers at any skill level to build API’s whether with REST or GraphQL. I think GraphQL is really cool but for the purposes of simplicity I will focus on building API routes in REST. If you aren’t already familiar with REST, REST stands for REpresentational State Transfer. In short, REST is a type of API that conforms to the design principles of the representational state transfer architectural style. And an API built correctly in REST is considered what’s called Restful. Check out more readings on REST here.

At a high level, normally, when building a full stack application, let’s say a MERN (MongoDB, Express, React and Node) application you’ll probably create some separation between both your client and your server code. You’ll probably create some server directory and in that directory you’ll create a standalone express server that then has a bunch of routes that will perform all of your various CRUD (Create, Read, Update and Delete) operations on your database. Then in your client code you’ll make GET/POSTS/PUT/DELETE requests to those various routes you’ve created server-side. Sometimes trying to follow how both the client and server code talk to each other can be really confusing.

Luckily, Next.js to the rescue πŸ™Œ. Next.js reduces this confusion and makes it pretty simple to create API routes that map to a particular file created in the pages/api directory structure. Let’s walk through it.

Quick note: We won’t focus on actually hitting a live database in this article. The main point I want to get across is how simple API’s can be built in Next.js. Hopefully with this simple mental model any developer should be able to expand on this information and create more complex applications.

The code for this article can also be found in this sandbox

Let’s start by creating a new Next.js application using the following command in your terminal.

npx create-next-app
#or
yarn create next-app

You’ll be asked to create a name for the project – just pick something 😎. After all the installation is complete, start the development server by running npm run dev or yarn dev in your terminal.

At this point, you should be able to visit http://localhost:3000 to view your application.

Now that everything is running, let’s head over to the pages/api directory. Inside of this directory create a new person directory. And inside of the person directory create two files index.js and [id].js (we’ll touch on this bracket syntax soon). Inside of the pages root directory, create another person directory with one file named [id].js in it. Lastly, in the root of your entire application, create a data.js file with the following code:

export const data = [
  
    id: 1,
    firstName: "LeBron",
    middleName: "Raymone",
    lastName: "James",
    age: 36,
  ,
  
    id: 2,
    firstName: "Lil",
    middleName: "Nas",
    lastName: "X",
    age: 22,
  ,
  
    id: 3,
    firstName: "BeyoncΓ©",
    middleName: "Giselle",
    lastName: "Knowles-Carter",
    age: 40,
  ,
];

Your pages directory structure should now look like the following:

- pages
  - /api
    - /person
      - [id].js
      - index.js  
  - /person
    - [id].js  

Any file inside the folder pages/api is automatically mapped to /api/* and will be treated as an API endpoint instead of a client-side page. Also, no need to worry about your client-side bundle size, these files are server-side bundled and won’t increase the code size going to the browser.

In the index.js file you just created in the person directory, paste the following snippet into your editor:

import  data  from "../../../data";

export default function handler(request, response) 
  const  method  = request;

  if (method === "GET") 
    return response.status(200).json(data);
  

  if (method === "POST") 
    const  body  = request;
    data.push( ...body, id: data.length + 1 );
    return response.status(200).json(data);
  

Let’s break this code down – for an API route to work you need to export a function, that receives two parameters: request: an instance of http.IncomingMessage and response: an instance of http.ServerResponse. Inside of this request handler you can handle different HTTP methods in an API route by using request.method which determines what HTTP method is being used by the request. In this code snippet, we are expecting either a GET or POST request. If we receive a GET request we will simply send a status of 200 and return the data in json form. If a POST request is received we will add what ever is sent over from the client via the body on the request to our array of data. You can think of this as if you were to perform a create operation on your database. Once we’ve completed this operation we will then also return a status of 200 and the current state of the data in json form.

Now let’s head over to pages/index.js, you should find a bunch of jsx that’s been provided by Next to render their custom home page. ERASE ALL OF IT 😈. And replace with the following code snippet:

import Link from "next/link";
import  useReducer, useState  from "react";

function reducer(state, action) 
  switch (action.type) 
    case "UPDATE_FIRST_NAME":
      return 
        ...state,
        firstName: action.payload.firstName
      ;
    case "UPDATE_MIDDLE_NAME":
      return 
        ...state,
        middleName: action.payload.middleName
      ;
    case "UPDATE_LAST_NAME":
      return 
        ...state,
        lastName: action.payload.lastName
      ;
    case "UPDATE_AGE":
      return 
        ...state,
        age: action.payload.age
      ;
    case "CLEAR":
      return initialState;
    default:
      return state;
  


const initialState = 
  firstName: "",
  middleName: "",
  lastName: "",
  age: ""
;

export default function Home() {
  const [state, dispatch] = useReducer(reducer, initialState);
  const [data, setData] = useState([]);

  const fetchData = async () => 
    const response = await fetch("/api/person");

    if (!response.ok) 
      throw new Error(`Error: $response.status`);
    
    const people = await response.json();
    return setData(people);
  ;

  const postData = async () => 
    const response = await fetch("/api/person", 
      method: "POST",
      headers: 
        "Content-Type": "application/json"
      ,
      body: JSON.stringify(state)
    );

    if (!response.ok) 
      throw new Error(`Error: $response.status`);
    

    dispatch( type: "CLEAR" );
    const people = await response.json();
    return setData(people);
  ;
  return (
    <div style= margin: "0 auto", maxWidth: "400px" >
      <div style= display: "flex", flexDirection: "column" >
        <label htmlFor="firstName">First Name</label>
        <input
          type="text"
          id="firstName"
          value=state.firstName
          onChange=(e) =>
            dispatch(
              type: "UPDATE_FIRST_NAME",
              payload:  firstName: e.target.value 
            )
          
        />
        <label htmlFor="middleName">Middle Name</label>
        <input
          type="text"
          id="middleName"
          value=state.middleName
          onChange=(e) =>
            dispatch(
              type: "UPDATE_MIDDLE_NAME",
              payload:  middleName: e.target.value 
            )
          
        />
        <label htmlFor="lastName">Last Name</label>
        <input
          type="text"
          id="lastName"
          value=state.lastName
          onChange=(e) =>
            dispatch(
              type: "UPDATE_LAST_NAME",
              payload:  lastName: e.target.value 
            )
          
        />
        <label htmlFor="age">Age</label>
        <input
          type="text"
          id="age"
          value=state.age
          onChange=(e) =>
            dispatch(
              type: "UPDATE_AGE",
              payload:  age: e.target.value 
            )
          
        />
      </div>
      <div
        style= marginTop: "1rem", display: "flex", justifyContent: "center" 
      >
        <button onClick=fetchData>FETCH</button>
        <button onClick=postData>CREATE</button>
      </div>
      <div>Data:</div>
      data ? <pre>JSON.stringify(data, null, 4)</pre> : null
      data.length > 0 ? (
        <div style= textAlign: "center" >
          Click a button to go to individual page
          <div
            style=
              marginTop: "1rem",
              display: "flex",
              justifyContent: "center"
            
          >
            data.map((person, index) => (
              <Link
                key=index
                href="/person/[id]"
                as=`/person/$person.id`
                passHref
              >
                <span
                  style=
                    padding: "5px 10px",
                    border: "1px solid black"
                  
                >`$person.firstName $person.lastName`</span>
              </Link>
            ))
          </div>
        </div>
      ) : null
    </div>
  );
}

Hopefully at this point you are pretty familiar with what’s going on here. It’s pretty basic React code. If you need to brush up on your React, head over to the documentation. The main things I want to point out here are the fetchData and postData handlers. You’ll notice that they are both performing fetch requests on the api/person endpoint that we created previously. As a reminder this is client-side code here so we can fetch just using the absolute path of api/person. The same doesn’t apply for server-side rendering requests and we will touch on that soon.

VoilΓ  πŸ‘Œ – this is the bread and butter of API routes in Next.js.

Open up your network tab in the devtools of your browser.

When you click the FETCH button in the UI, you’ll notice a GET request is made to api/person and the response is the data that we hard-coded.


      id: 1,
      firstName: "LeBron",
      middleName: "Raymone",
      lastName: "James",
      age: 36,
    ,
     
      id: 2, 
      firstName: "Lil", 
      middleName: "Nas", 
      lastName: "X", 
      age: 22 
    ,
    
      id: 3,
      firstName: "BeyoncΓ©",
      middleName: "Giselle",
      lastName: "Knowles-Carter",
      age: 40,
,

You’ll also notice that a POST request is sent if you fill out the form inputs and click the CREATE button.

Again, you can imagine that in your API code you’re performing some read and create operations on your database and returning the expected data. For this example I wanted to keep it simple.

Let’s head over to the pages/person/[id].js file and paste this snippet into the editor:

import  data  from "../../../data";

export default function handler(request, response) 
  const  method  = request;

  if (method === "GET") 
    const  id  = request.query;

    const person = data.find((person) => person.id.toString() === id);

    if (!person) 
      return response.status(400).json("User not found");
    

    return response.status(200).json(person);
  

You might be wondering, what’s up with the bracket syntax? Well, the short of it is Next.js provides a way for developers to create dynamic routing. The text that you put in between the brackets work as a query parameter that you have access to from the browser url. More info on dynamic routes can be found in the docs. Breaking down this snippet above we are expecting a GET request that will carry an id on the request.query object. Once we have access to this id we can then search our “database” for a person whose id matches the id provided by the request. If we find a person then we return it in json format with a status of 200. If not, we return an error of 400 with a message User not found. However, there’s still one more step. Remember this is just the api step, we still need to render a page for our individual person.

Let’s hop over to person/[id].js and paste the following code snippet:

import  useRouter  from "next/router";

const Person = ( user ) => 
  const router = useRouter();

  return (
    <div>
      <button onClick=() => router.back()>Back</button>
      <pre>JSON.stringify(user, null, 4)</pre>
    </div>
  );
;

export async function getServerSideProps(context) 
  const  id  = context.params;
  const user = await fetch(`http://localhost:3000/api/person/$id`);
  const data = await user.json();

  if (!data) 
    return 
      notFound: true
    ;
  

  return 
    props:  user: data 
  ;


export default Person;

Let’s break this down – if we look back at pages/index.js you’ll find the following snippet:

data.map((person, index) => (
               <Link
                key=index
                href="/person/[id]"
                as=`/person/$person.id`
                passHref
              >
                <span
                  style=
                    padding: "5px 10px",
                    border: "1px solid black"
                  
                >`$person.firstName $person.lastName`</span>
              </Link>
))

You’ll notice that we are mapping over each person in our data and rendering Link tags for each of them. Next.js provides Link tags that can be used for client-side transitions between routes. In our case we are expecting each Link to transition to person/[id] page, the id being the one provided on each person object. So when the user clicks one of these links, Next.js will transition to the appropriate page, for example person/2.

By default, Next.js pre-renders every page. This means that Next.js will create HTML for each page in advance, instead of having it all done via client-side Javascript. You can pre-render either by Static Generation or Server-side rendering. Since our app relies on “frequently updated data fetched from an external API” we will go the server-side rendering route.

This leads us back to the person/[id].js file. You’ll notice that we are exporting an async function called getServerSideProps. This is one of helper functions that Next.js provides us for pre-rendering a server-side page. Each request will pre-render a page on each request using the data return back from this function. The context parameter is an object that contains useful information that can be used to in this function. In our case we want to get access to the id that’s been passed in the request using the context.params object. More information on the context parameter here.

Once we have access to the id we make a fetch request to http://localhost:3000/api/person$id. Notice we have to provide the full absolute url including the scheme (http://), host (localhost:) and port (3000). That’s because this request is happening on the server not the client. You have to use an absolute URL in the server environment NOT relative. Once the request is successful, we format the data to json and check whether we have data or not. If not, we return an object with notFound: true. This is some Next.js magic that tells the component to render a 404 status page. Otherwise, if we have data we will return a prop object which will be passed to the page components as props. In our case we will pass along the data we’ve received from the request to the Person component. In our Person component, we are destructioning user off of the props and using it to display.

And that’s pretty much it. There’s a ton more detail I could’ve delved into but hopefully on a high level you now have a better understanding of how Next.js API routes work.

Connect with me on Twitter and on LinkedIn




Source link