Security News
Node.js EOL Versions CVE Dubbed the "Worst CVE of the Year" by Security Experts
Critics call the Node.js EOL CVE a misuse of the system, sparking debate over CVE standards and the growing noise in vulnerability databases.
pojo-observer
Advanced tools
A minimalist object observer that works with React hooks.
Because you you can separate presentation logic from interaction logic.
Create a POJO subject (Plain Old Javascript Object - POTO if using Typescript?), and have your React component update whenever that subject changes through an useObserver
hook.
Say you have this Gallery component. An ultra thin UI component with presentation logic only:
import useObserver from 'pojo-observer'
// It's up to you how the inject the subject. Perhaps use depedency injection + a composite root
export default function GalleryUI({gallery}) {
// Place the hook at the top of your component just like any other React hook
useObserver(gallery)
return (
<>
<h5>Component</h5>
// Changes in the gallery object will be updated here whenever the subject changes
<p>Image = [{gallery.currentImage()}]</p>
// act directly on the subject
<button onClick={gallery.previousImage}>Previous Image</button>
<button onClick={gallery.nextImage}>Next Image</button>
</>
)
}
And this POJO:
export default class Gallery {
constructor() {
this._images = []
this._selectedImage = 0
}
nextImage() {
if (this._selectedImage < this.images.length - 1) {
this._selectedImage++
}
}
previousImage() {
if (this._selectedImage > 0) {
this._selectedImage--
}
}
addImage(image) {
this._images.push(image)
}
currentImage() {
return this._images[this._selectedImage]
}
}
And now any time a value inside the POJO changes, the useObserver
hook will re-render the component. Sweet!
Bonus: You can test the heck out of the interaction now without having to mess with any UI testing libraries.
Now let's assume we have some async function on that object happening.
// ... truncated for brevity
constructor() {
// ... truncated for brevity
setInterval(this.nextImage, 1000)
// ... truncated for brevity
Yes yes, never put a setInterval in a constructor. But say you have an external event that updates the model, well, the React component will update. Sweet!
You can also add as many other hooks like useEffect
as you like as follows:
// ...
// You can have effet react to specific queries
useEffect(() => {
console.log('effect currentImage()')
// since you have commands, you no longer need to dispatch events with reducers.
// You can work with the POJO directly and handle all complexities there
// gallery.doSomething(...)
}, [gallery.currentImage()])
useEffect(() => {
console.log('effect images')
// gallery.doSomethingElse(...)
}, [gallery._images]) // you can also access member variables directly since the command will trigger a rerender, though it's advised you don't do this as it couples your view to your POJO. It could be useful for debugging.
// ...
They work :)
Check out the pureObserver.spec.tsx
file for the cases we've thought of, and please report any issues you find as a test if possible and we'll work on it.
This library and all the ones mentioned above are ultimately implementations of the Observer Pattern. (Redux is more of a state management library but it also has an observer when using the Connect method).
This library is a minimal observer pattern implementation that takes in a POJO as a subject, instruments it, and performs callbacks when the subject has changed. It's not opinionated at all and allows you to use it however you see fit, like choosing the event library to add (or not).
It's also tiny at around ~4k minified.
At Xolv.io we are big fans of BDD (Behaviour Driven Development), DDD (Domain Driven Design) and the Clean Architecture, and we love to make things as simple as possible.
While working with clients and seeing how complex UI's have become, the question of "is it possible to do DDD in the UI?" kept coming up. We've had great success at helping clients do BDD, DDD, and Clean Architecture in the back-end in order to reduce complexity, increase quality, and improve speed and maintainability (shameless plug for our consulting services here), so we wanted to see how to do this in the front-end.
The following inferences were made:
In the world of front-ends, the above inferences result in the following implications:
From BDD:
From DDD
From Clean Architecture
Side notes:
But in order to do any of the above, one has to completely decouple the presentation layer from the layers beneath. And while it's possible to do so with the right coding practices, we found there was a lot of boilerplate in binding data to the UI. If we could somehow just focus on the interaction modeling and then plug a UI on top that requires minimal boilerplate code and is highly decoupled, that would allow us to move fast and to have highly testable code. Moreover, it would not lock us in to any framework.
This is why this library was dreamt up.
Having an abstract interaction object has many advantages:
FAQs
A minimalist object observer that works with React hooks.
The npm package pojo-observer receives a total of 54 weekly downloads. As such, pojo-observer popularity was classified as not popular.
We found that pojo-observer demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Critics call the Node.js EOL CVE a misuse of the system, sparking debate over CVE standards and the growing noise in vulnerability databases.
Security News
cURL and Go security teams are publicly rejecting CVSS as flawed for assessing vulnerabilities and are calling for more accurate, context-aware approaches.
Security News
Bun 1.2 enhances its JavaScript runtime with 90% Node.js compatibility, built-in S3 and Postgres support, HTML Imports, and faster, cloud-first performance.