
Product
Announcing Socket Fix 2.0
Socket Fix 2.0 brings targeted CVE remediation, smarter upgrade planning, and broader ecosystem support to help developers get to zero alerts.
@unnamed-projects/mutojs
Advanced tools
Tool for dispatching actions from React Client Components to React Server Components
muto.js
is a tool for dispatching actions from React Client Components to React Server Components in a type safe way
React Server Components are still very experimental. I'm not even sure if this is lib is a good idea, but it was fun to make. :)
pnpm i @up/mutojs
// src/app/muto.ts
import { createMuto } from '@up/mutojs'
import sql from '../db'
export const muto = createMuto({
name: 'myMuto',
mutations: {
async deleteTag(id: number) {
const resp = await sql`
DELETE FROM tags
WHERE id = ${id};
`
return resp
},
},
})
// export your action creators
// Note: muto and actions can only be imported in server components
export const { deleteTag } = muto.actions
// src/app/page.tsx
import sql from './db'
import { DeleteTagButton } from './DeleteTagButton'
import { deleteTag } from './muto'
// This is a Server Component
export default async function () {
const tags = await sql`SELECT id, title FROM tags`
return (
<div>
{tags.map((tag) => (
<DeleteTagButton mutoDeleteTagAction={deleteTag(tag.id)} />
))}
</div>
)
}
// src/app/DeleteTagButton.tsx
// this is a client component
'use client'
import { AppMutoActions, useAppMuto } from '@/app/appMuto/useAppMuto'
export function DeleteTagButton({ mutoDeleteTagAction }) {
const mutate = useAppMuto(mutoDeleteTagAction)
return <button onClick={mutate}>Remove Tag</button>
}
// src/app/api/mutations/route.ts
import { mutoRouteHandler } from '@up/mutojs'
import { muto } from '../../../muto.ts'
export async function POST(request: Request) {
return mutoRouteHandler(request, { [muto.name]: muto })
}
The deleteTag
action function creates a serialized payload that can be passed from a Server Component to a Client Component.
This payload contains:
{
name: 'myMuto', // the name of your muto collection
mutationName: 'deleteTag', // a function to call in that collection
payload: <tag.id> // The args to call the mutation function with. In this case a tag id
}
The useAppMuto
hook does two things:
router.refresh()
, causing the app to re-render displaying the results of the mutationThe mutoRouteHandler
takes the payload and uses it to call the appropriate mutation function, returning it's result!
import { createMuto } from '@up/mutojs'
export const muto = createMuto({
name: 'myMuto',
mutations: {
async createTag(title) {
const resp = await sql`
INSERT INTO tags (title) VALUES (${title})
RETURNING id
`
// resp's type is postgres.RowList<postgres.Row[]>
return resp
},
},
})
export const { createTag } = muto.actions
// Create a type for your application's Muto
// Types can be imported in both client and server
export type AppMuto = typeof muto
// src/app/useAppMuto.ts
import {
useMuto,
StringifiedMutoActions,
MutoActionKeys,
MutoAppActions,
} from '@up/mutojs'
import type { AppMuto } from '.muto.ts'
// Should be the path to your Next Route Handler
const baseUrl = 'http://localhost:3000/api/mutations'
export const useAppMuto = (action: StringifiedMutoActions<AppMuto>) =>
useMuto<AppMuto>(baseUrl, action)
export type AppMutoActions<T extends MutoActionKeys<AppMuto>> = MutoAppActions<
AppMuto,
T
>
// src/app/AddTagButton.tsx
'use client'
import { AppMutoActions, useAppMuto } from '@/app/appMuto/useAppMuto'
interface AddTagButtonProps {
// AddTagButton only accepts `createTag` action payloads!
mutoAction: AppMutoActions<'createTag'>
}
export function AddTagButton({ mutoAction }: AddTagButtonProps) {
const mutate = useAppMuto(mutoAction)
return (
<button
onClick={async () => {
// resp's type is postgres.RowList<postgres.Row[]>!
const resp = await mutate()
}}
>
Add Tag
</button>
)
}
// src/app/page.tsx
export default async function () {
// TS ERROR! deleteTag is not assignable to type createTag
return <AddTagButton mutoAction={createTag('My cool tag!')} />
}
FAQs
Tool for dispatching actions from React Client Components to React Server Components
We found that @unnamed-projects/mutojs 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.
Product
Socket Fix 2.0 brings targeted CVE remediation, smarter upgrade planning, and broader ecosystem support to help developers get to zero alerts.
Security News
Socket CEO Feross Aboukhadijeh joins Risky Business Weekly to unpack recent npm phishing attacks, their limited impact, and the risks if attackers get smarter.
Product
Socket’s new Tier 1 Reachability filters out up to 80% of irrelevant CVEs, so security teams can focus on the vulnerabilities that matter.