DEV Community

Vinicius Basilio
Vinicius Basilio

Posted on

Make React from scratch for fun

Hello, fellow React enthusiasts! I'm super excited to share with you a little project I've been working on: creating my own “React” library from scratch. You might be wondering why you would want to create your own React library when there are so many great ones out there already. In my case, just for fun.

This project is all about pure javascript and html, no other libraries or frameworks needed. We will create our own state hooks to manage the data and the UI. It will be fun and challenging, but also rewarding and educational.

First, we need to create a central place to store our states. Instead of using a plain object, we'll use a Map, which is a data structure that lets us store key-value pairs and perform operations on them easily. MDN recommends using a Map when you need to add or remove keys frequently, which is exactly what we'll do. We'll also create a custom function to access and update our Map, using functional programming principles (because it function).

let memory = new Map();

const defaultGetter = (signature) => () => memory.get(signature);
const defaultSetter = (signature) => (data) => {
  memory.set(signature, data);
  return render();
};
Enter fullscreen mode Exit fullscreen mode

It's time to learn how to make our own custom hooks. We will explore three different types of hooks: a general one, a switch one, and an array one. A general hook can be used for any kind of state management. A switch hook can toggle between true and false values. An array hook can add or remove items from an array. Sounds exciting, right? Let's get started!

First hook:

const createState = (init) => {
  const signature = memory.size;
  memory.set(signature, init);
  const getter = defaultGetter(signature);
  const set = defaultSetter(signature);

  const setter = (newValue) => {
    return set(newValue);
  };
  return [getter, setter];
};
Enter fullscreen mode Exit fullscreen mode

How to use:

const [stringExample, setStringExemple] = createState('Joe');
console.log(stringExample()); // joe
setStringExemple('Joe Joe');
console.log(stringExample()); // Joe Joe
Enter fullscreen mode Exit fullscreen mode

Boolean hook:

const createBoolean = (init, condition) => {
  const signature = memory.size;
  memory.set(signature, init);
  const getter = defaultGetter(signature);
  const set = defaultSetter(signature);

  const setter = (newValue) => {
    switch (newValue) {
      case condition[0]:
        set(true);
        break;
      case condition[1]:
        set(false);
        break;
      default:
        console.error(`Sorry, something wrong`);
        set(false);
    }
  };
  return [getter, setter];
};
Enter fullscreen mode Exit fullscreen mode

How to use:

const [IsLightOn, setIsLightOn] = createBoolean(false, ["turnOn", "turnOff"]);

console.log(IsLightOn()); // false
setIsLightOn("turnOn");
console.log(IsLightOn()); // true
setIsLightOn("turnOff");
console.log(IsLightOn()); // false
Enter fullscreen mode Exit fullscreen mode

Array hook:

const createArray = (init) => {
  const signature = memory.size;
  const get = defaultGetter(signature);
  const set = defaultSetter(signature);

  Array.isArray(init)
    ? memory.set(signature, init)
    : memory.set(signature, [init]);

  const getter = (index) => {
    if (typeof index == "number") {
      return get()[index];
    }
    return get();
  };

  const setter = (index, newValue) => {
    if (newValue !== undefined && !Array.isArray(index)) {
      const newArr = [];
      newArr[0] = index;
      set(newArr);
    } else if (Array.isArray(index)) {
      set(index);
    } else {
      const arr = get();
      arr[index] = newValue;
      set(arr);
    }
  };
  return [getter, setter];
};
Enter fullscreen mode Exit fullscreen mode

How to use:

const [array, setArray] = createArray("index 0");
console.log(array()); // [ 'index 0' ]
setArray([...array(), "index 1"]);
console.log(array()); // [ 'index 0', 'index 1' ]
console.log(array(1)); // index 1
Enter fullscreen mode Exit fullscreen mode

We are almost done with our app! Now it's time to make our render function to update UI. This function will take the state of our app and display it on the screen. It will also handle any user interactions and events. Let's get started!

const appDiv = document.getElementById("app");

function render() {
  appDiv.innerHTML = App();
}
Enter fullscreen mode Exit fullscreen mode

Alright, time to write our first component and test! This is going to be fun and easy.

const [hellomsg, setHellomsg] = createState("Hello, world!");
const update = () => setHellomsg("Hi, there!");

const App = () => {
  return `<div>
            <h1>${hellomsg()}</h1>
            <button onclick="update()">Change the msg</button>
          </div>
`;
};
Enter fullscreen mode Exit fullscreen mode

Your code will be like this:

const [hellomsg, setHellomsg] = createState("Hello, world!");
const update = () => setHellomsg("Hi, there!");

const App = () => {
  return `<div>
            <h1>${hellomsg()}</h1>
            <button onclick="update()">Change the msg</button>
          </div>
`;
};

const appDiv = document.getElementById("app");

function render() {
  appDiv.innerHTML = App();
}

render(); //don't forget to initialize

Enter fullscreen mode Exit fullscreen mode

Don't worry, I have more tricks up my sleeve, I'm working on another hook that I'll share soon. Let me know what you think. You can find the code on my github later.

Top comments (1)

Collapse
 
tinkerbaj profile image
tinkerbaj

Nice its sound promising.