Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
July 27, 2022 07:40 pm GMT

I created a framework with JSX components on generators*, a fast mobx-like state management and an exclusive cssx styling system

Hi guys!

My name is Dani. For several years now, I have been experimenting with different approaches to front-end development. I tried many different ideas, the best of which I collected in my framework Whatsup. In this article, I want to briefly tell you about architectural decisions and discuss them with you in the comments.

Short features list

  • easy to use: simple api, just write code
  • own reactivity system with high performance
  • cool styling system based on css modules
  • glitch free, autotracking and updating of dependencies
  • written in typescript, type support out of the box
  • small size: ~7kB gzipped (state + jsx + cssx)

JSX components on generators

It seems to me that one day the React team really wanted to get rid of class components in order to leave only functional ones. But there was a problem - the functional components are called every time when rendering and you need to somehow transfer the state from render to render. They came up with hooks... Now we all use hooks... When javascript has generators... Just take a look at how using native language constructs you can describe the life cycle of a component.

function* App() {    // componentWillMount    try {         while (true) {             // main life cycle            yield <div>Hello</div>        }    } catch (e) {        // componentDidCatch    } finally {        // componentDidUnmount    }}

It may seem unusual at first glance, but believe me - it's very simple. All variables you declare in the componentWillMount phase will be available from render to render, no magic - that's the nature of generators.

With try{}catch{} you can easily handle errors. And it's native javascript capabilities, isn't that great?

However, you are not required to write try{}catch{}finally{} in each component, only where it's really needed. For example, we only need to control the componentWillMount and componentDidUnmount phases:

function* App() {    // componentWillMount    try {         while (true) {             // main life cycle            yield <div>Hello</div>        }    } finally {        // componentDidUnmount    }}

Or we only need the componentWillMount phase:

function* App() {    // componentWillMount     while (true) {         // main life cycle        yield <div>Hello</div>    }}

And if we dont need to control any phases at all, then we just use a regular functional component:

function App() {    return <div>Hello</div>}

Mobx-like state management

I have been using React + Mobx for many years. I love that Mobx allows you to write intuitive code that is easy to read and maintain. But I always lacked the ability to use generators to create computed atoms.

const timer = computed(function*(){    const count = observable(0)    const intervalId = setInterval(()=> count(count() + 1), 1000)    try {        while(true){            yield count()        }    } finally {        clearInterval(intervalId)    }})autorun(()=> console.log(timer())//> 1//> 2//> 3

In this example, all the components necessary for the timer to work are encapsulated in the body of the generator. I find this to be a very slick solution. Mobx does not provide us with such opportunities.

A computed atom can also be created from a normal function

const count = observable(0)const text = computed(()=> `Count is: ${count()}`)autorun(()=> console.log(text())//> Count is: 0count(1)//> Count is: 1

As you may have noticed, getting a value from a computed or an observable is done with a call without arguments (count() text()), and setting a value in an observable is a call with an argument (count(1)).

In all other respects, the state management API is very similar to Mobx and includes the following components:

  • observable - creates a trackable atom
  • array, map, set - creates a trackable array, map, set
  • computed - creates a derived atom
  • action, runInAction - allows multiple updates in one operation
  • autorun, reaction - trigger side effects when observed values change
  • mutator - allows you to create new data based on previous

CSSX styling system

This is a hybrid of css-modules and jsx namespaces, that uses the sass language to describe the styles of the components.
Consider this example:

// styles.scss.box {    width: 50px;    height: 50px;}

We can use it like regular css modules

import styles from './styles.scss'function Box(){    return <div className={styles.box} />}

We can bind styles to a component using the cssx function and then apply the .box class to an element using a namespaced property css:box

import styles from './styles.scss'import { cssx } from 'whatsup/cssx'const Div = cssx('div', styles)function Box(){    return <Div css:box />}

Or we can immediately import the component with binded styles from the css file (this way we can import any standard html tag)

import { Div } from './styles.scss' function Box(){    return <Div css:box />}

Among other things, you can import style files and access their styles, for example:

// styles.scss@import 'grid.scss';.box {    width: 50px;    height: 50px;}

And now we can arrange our box according to the grid rules

import { Div } from './styles.scss' function Box(){    return <Div css:box css:sm_col_2 css:md_col_3 />}

And for all this, Whatsup provides intellisense

Image description

Our first component

Well, let's summarize our knowledge and write our first component. Let's make a box that changes color on click.

// styles.scss .box {    width: 50px;    height: 50px;}.coral {    background-color: coral;}.green {    background-color: green;}
import { observable } from 'whatsup'import { render } from 'whatsup/jsx'import { Div } from './styles.scss'export function Box() {    const color = observable('coral')     const onClick = () => color(color() === 'coral' ? 'green' : 'coral')    while (true) {         yield (            <Div                 css:box                css:coral={color() === 'coral'}                 css:green={color() === 'green'}                 onClick={onClick}            />         )    }}render(<Box />)

And we can look at the result and sources

Want to try?

Just run this in your terminal

npx @whatsup/cli create project

Conclusion

The frontend world is rapidly evolving. New projects come to replace the old ones. Only the most courageous and ambitious survive.I like to search and find original ideas, I hope that my article was useful to you.
Thank you for reading, and let's connect!

Links

GitHub logo whatsup / whatsup

A frontend framework for chillout-mode development JSX components on generators, fast mobx-like state management and exclusive cssx style system

What is it?

Whatsup is a modern frontend framework with own reactivity system and JSX components based on pure functions and generators.

Features

  • easy to use: simple api, just write code
  • own reactivity system with high performance
  • cool styling system based on css modules
  • built-in router with intuitive api
  • glitch free, autotracking and updating of dependencies
  • written in typescript, type support out of the box
  • small size: ~7kB gzipped (state + jsx + cssx)

Example

import { observable } from 'whatsup'import { render } from 'whatsup/jsx'function* App() {    const counter = observable(0)    const increment = () => counter(counter() + 1)    while (true) {        yield (            <div>                <p>You click {counter()} times</p>                <button onClick=

Original Link: https://dev.to/iminside/i-created-a-framework-with-jsx-components-on-generators-a-fast-mobx-like-state-management-and-an-exclusive-cssx-styling-system

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To