react layers, yet another microframework on top of react

asmer ced31b930a pub-query checks: mutations and mutations refresh 3 ヶ月 前
public 7dae679ad0 initial: pub and usePub 3 ヶ月 前
src ced31b930a pub-query checks: mutations and mutations refresh 3 ヶ月 前
README.md 4d5970651e pub-query begins 3 ヶ月 前
index.html 7dae679ad0 initial: pub and usePub 3 ヶ月 前
package-lock.json 1656af2bba NamedRoute and NamedLink 3 ヶ月 前
package.json 1656af2bba NamedRoute and NamedLink 3 ヶ月 前
tsconfig.app.json 7dae679ad0 initial: pub and usePub 3 ヶ月 前
tsconfig.json 7dae679ad0 initial: pub and usePub 3 ヶ月 前
tsconfig.node.json 7dae679ad0 initial: pub and usePub 3 ヶ月 前
vite.config.ts 7dae679ad0 initial: pub and usePub 3 ヶ月 前

README.md

Rayers. React layers.

Description

React Layers

NIH-syndrom again

Goal

Create layered React microframework with reasonable architecture and minimal boilerplate.

Architecture

Layers, one-by-one from deepest layer (global state management, server queries) to directly View (react) layer:

Pub (and Sub)

Minimalistic pub/sub with recursive support builded on top of Javascript Proxy

const pub = createPub()
pub.subscribe((state, key, oldValue, newValue) => console.log(state, key, oldValue, newValue))

pub.a = 5
pub.arr = ['foo', 'bar']
pub.arr[1] = 'baz'

On any change of keys in objects subscriber called. You can listen to updates in any nested object. Listening on upper level hears also nested updates. This way you can achieve global state tree without boilerplate, but this way requires attention to what you do with state.

React Listening Hook

usePub, obviously. Causes react component update on changing of pub. To minimize overhead, usePub can be used for nested pubs, instead of root state.

const arrPub = usePub(pub.arr)

Hook returns pub, so arrPub === pub.arr, but component updating when pub changes.

Network Requests/Promises

Pub can be easily used for tracking promises. !!! (error) Be careful, storing promises in global state causes memory leaks !!!

How
  1. creating nested Pub with structure like javascript { promiseName1: {status, payload, error} promiseName2: {status, payload, error} }
  2. Writing function, which have promiseName and exactly promise as argument and updates promise pub branch when promise updating its state (PENDING => FULFILLED or PENDING => REJECTED), storing status, payload and error in promise pub named branch
  3. rtk-query:
    • composing functions: query function, which returns promise and "thunk", which passed promise life through pub. Something like createAsyncThunk, or createQuery, with next parameters:
      • promiseName.
      • queryFunc - function, which returns promises.

    or even carrying:

    1. `createQueryPub` creates pub with promises, some basic options passed (like cache timeout and probably queryFunc) and returns `createQuery` or object with functions from step 3 if queryFunc passed on first step into createQueryPub
    2. `createQuery(queryFunc)` returns function, which:
    3.  receives `promiseName`, returns object with functions:
        - `query`, which accepts arguments and passes it to `queryFunc`
        - `usePromiseNameQuery`/`usePromiseNameMutation` like in `rtk-query`
        - and so... (no ideas right now, but something about atomic actions/force query/invalidate cache)
    

Actions/Controllers/Thunks

To avoid random messy access to global state, some functions which works with are welcome, but they aren't necessary.

Routing

Instead of moving Routing on React level, making routing great again separated from React Markup.

Why

  • Because
  • Routing describes page content overall, but not how it will exactly looks (React does)
  • Routing describes request to backend, regardless of look.

Two layers of routing:

  • address routing
  • hash routing

Conclusion

Routing configuration should be separated from React markup, and store next information:

  • Route Template like /page/:id
  • Route Name which probably same as one of promise names
  • Query Func or even Query Params to make query with Pub. Query Func can be made very easy with GraphQL. Query Func gets all information about route (or, at least, params from route) as function parameters to make query. Usually Query Func is just thunk with promise for Pub.
  • React Page Component, which should be rendered for this Route. Probably with MetaPlate to avoid props drilling, useHuy, map, props waterfall, usePizda, map and so
  • Some private routing configuration, like fallback (address to go, if private route not accessible) and roles - list of user roles, which can visit this private page. Some HOC needed to provide current user roles list (usually from global state/jwt) to be matched with roles props

some ideas and thoughts

  • address routing (from domain till ?
  • hash routing (from # till end of address)

possible routing configuration:

  • list style, as JSON or JSX (like )
  • tree style, potentially faster (but it doesn't matters on client side) javascript const treeRouteConfig = { //root page: "/": PageMain, //login '/login': PageLogin, //admin part with subroutes '/admin': { "/": PageAdminMain, // /admin/ "/users": PageAdminUsers, // /admin/users } }

A lot of questions at the moment about three configs: what if route params AND nested routes ?-params and hash layer - where is should be configured? looks like this configuration should be moved into page component, not to be in tree. so cancel tree idea for now

View Layer (react)

Mostly template react components without boilerplate, hookafucking, billions of useEffect and so. Styling moved to CSS or... not.

Tools

  • createPub and qjp (should be refucktored) from v01
  • Some wrapper around react-router-dom to pass query func to Route component or other configuration
  • Metaplate, which provides meta templating abilities to write nesting components page layout, according to nested query data without boilerplate and map
  • Something for SSR

Additionals

Some addons

SSR

For now no implementations about SSR, but there are some ideas:

  • CSSR. Client Server Side Rendering lol. Draw HTML in user browser, then upload it back to backend. Pros and cons:
    • Pros:
      • no need of backend SSR code
      • no load on server
    • Cons:
      • client-side load
      • client can scam
      • no SEO HTML before user comes to page
  • Simplicity. No backend code with all this SSR boilerplate. Using maximal isomorphy as it possible.
    • Components may have stub version.
    • DOM-Elements and/or Components may be marked as private for sensual information. This DOM-Elements or Components should not be rendered on backend (only stub rendered)
    • Marking components/elements as private gives ability to get seamless SSR without almost coding on backend.

TODO

  • Check speed or MetaPlate on huge updates.
  • Wrapper around react-router-dom.
  • SSR library