Research
Security News
Threat Actor Exposes Playbook for Exploiting npm to Build Blockchain-Powered Botnets
A threat actor's playbook for exploiting the npm ecosystem was exposed on the dark web, detailing how to build a blockchain-powered botnet.
A state manager for React, built on [Zustand](https://github.com/pmndrs/zustand), with built-in undo, redo and persistence.
A state manager for React, built on Zustand, with built-in undo, redo and persistence.
💜 Consider becoming a sponsor.
npm install rko
or
yarn add rko
To use the library, first define your state as a class that extends StateManager
.
// state.ts
import { StateManager } from 'rko'
// Define a type for your state
interface State {
name: string
count: number
}
// Extend StateManager to define your state
class MyState extends StateManager<State> {
adjustCount = (n: number) =>
this.setState({
before: {
count: this.state.count,
},
after: {
count: this.state.count + n,
},
})
}
// Create and export an instance of your state
export const myState = new MyState(
{
name: 'Steve',
count: 0,
},
'my-state'
)
Then use the useStore
hook to access the state. For more on the useStore
hook, see zustand's documentation. You can also use your methods (e.g. increment
) directly, as well as the StateManager
's built-in methods (e.g. undo
, redo
and reset
).
// app.tsx
import { myState } from './state'
export default function App() {
// Select items from the zustand state
const { name } = myState.useStore((s) => s.name)
const { count } = myState.useStore((s) => s.count)
// Call methods on the state
function increment() {
myState.adjustCount(1)
}
function decrement() {
myState.adjustCount(-1)
}
return (
<div>
<h1>Hello {name}</h1>
<h2>Count: {count}</h2>
<button onClick={increment}>Increment</button>
<button onClick={decrement}>Decrement</button>
<button onClick={myState.undo}>Undo</button>
<button onClick={myState.redo}>Redo</button>
<button onClick={myState.reset}>Reset</button>
</div>
)
}
You can use the StateManager
class to create a state manager for your app. You will never use StateManager
directly. Instead, you will extend the StateManager
class and add methods that use its internal API in order to create a state manager for your particular app.
When you create an instance of your StateManager
sub-class, you pass in your initial state (an object). You can also pass in an id
string, which will be used to persist the state.
In your class definition, you can define methods that update your state using StateManager
's internal API.
patchState(patch: Patch<T>)
Update the state without effecting the undo/redo stack. This method accepts a Patch
type object, or a "deep partial" of the state object containing only the changes that you wish to make.
Example:
toggleMenuOpen = () =>
this.patchState({
ui: {
menuOpen: !this.state.ui.menuOpen,
},
})
setState(command: Command<T>)
Update the state and push the command to the undo/redo stack. This method accepts a Command
type object containing two Patch
es: before
and after
. The after
patch should contain the changes to the state that you wish to make immediately and when the command is "re-done". The before
patch should contain the changes to make when the command is "undone".
adjustCount = (n: number) =>
this.setState({
before: {
count: this.state.count,
},
after: {
count: this.state.count + n,
},
})
cleanup(state: T, patch: Patch<T>)
The cleanup method is called on every state change, after applying the current patch. It returns the "final" updated state. You can override this method in order to clean up any state that is no longer needed. For example, if you have a state that is a list of items, you can use the cleanup method to remove items that are no longer in the list. Note that the changes won't be present in the undo/redo stack.
cleanup = (state: T, patch: Patch<T>) => {
const final = { ...state }
for (const id in todos) {
if (!todos[id]) {
delete final.todos[id]
}
}
return final
}
You can also use the cleanup
method to implement middleware or other functionality that needs to occur on each state change.
The StateManager
class exposes a public API that you can use to interact with your state either from within your class methods or from anywhere in your application.
undo()
Move backward in history, un-doing the most recent change.
redo()
Move forward in history, re-doing the previous undone change.
reset()
Reset the state to its original state. Also reset the history.
resetHistory()
Reset the state's history.
forceUpdate()
Force the state to update.
setSnapshot()
Save the current state to the the snapshot
property.
snapshot
The saved snapshot. You can use the snapshot
to restore earlier parts of the state.
Please open an issue for support.
Have an idea or casual question? Visit the discussion page.
FAQs
- [Installation](#installation) - [Usage](#usage) - [Advanced Usage](#advanced-usage) - [Examples](#examples) - [Support](#support) - [Discussion](#discussion) - [Author](#author)
The npm package rko receives a total of 1,764 weekly downloads. As such, rko popularity was classified as popular.
We found that rko 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.
Research
Security News
A threat actor's playbook for exploiting the npm ecosystem was exposed on the dark web, detailing how to build a blockchain-powered botnet.
Security News
NVD’s backlog surpasses 20,000 CVEs as analysis slows and NIST announces new system updates to address ongoing delays.
Security News
Research
A malicious npm package disguised as a WhatsApp client is exploiting authentication flows with a remote kill switch to exfiltrate data and destroy files.