<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: purposewalker</title>
    <description>The latest articles on DEV Community by purposewalker (@purposewalks9).</description>
    <link>https://dev.to/purposewalks9</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3650863%2F11d58617-0623-43b7-ab4f-292bf5360b88.png</url>
      <title>DEV Community: purposewalker</title>
      <link>https://dev.to/purposewalks9</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/purposewalks9"/>
    <language>en</language>
    <item>
      <title>Hookraft</title>
      <dc:creator>purposewalker</dc:creator>
      <pubDate>Fri, 10 Apr 2026 18:33:48 +0000</pubDate>
      <link>https://dev.to/purposewalks9/hookraft-26pa</link>
      <guid>https://dev.to/purposewalks9/hookraft-26pa</guid>
      <description>&lt;p&gt;made a hook that tracks user engagement (clicks, scroll, time, idle)&lt;br&gt;
no sdk, no setup stress&lt;br&gt;
just data + your own backend&lt;br&gt;
kinda crazy how simple it feels&lt;br&gt;
&lt;a href="https://hookraft.site/docs/use-engagement" rel="noopener noreferrer"&gt;https://hookraft.site/docs/use-engagement&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Hookraft</title>
      <dc:creator>purposewalker</dc:creator>
      <pubDate>Wed, 01 Apr 2026 15:51:26 +0000</pubDate>
      <link>https://dev.to/purposewalks9/hookraft-169o</link>
      <guid>https://dev.to/purposewalks9/hookraft-169o</guid>
      <description>&lt;p&gt;State sync across tabs… without a backend 🤯&lt;br&gt;
useBroadcast uses the BroadcastChannel API to keep everything in sync instantly.&lt;br&gt;
New hook just dropped 👇&lt;br&gt;
&lt;a href="https://hookraft.site/docs/use-broadcast" rel="noopener noreferrer"&gt;https://hookraft.site/docs/use-broadcast&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu4gtokhwjkw9nieaxc4v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu4gtokhwjkw9nieaxc4v.png" alt=" " width="800" height="460"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>nextjs</category>
      <category>react</category>
      <category>web</category>
    </item>
    <item>
      <title>Hookraft</title>
      <dc:creator>purposewalker</dc:creator>
      <pubDate>Tue, 31 Mar 2026 16:56:18 +0000</pubDate>
      <link>https://dev.to/purposewalks9/hookraft-3bhf</link>
      <guid>https://dev.to/purposewalks9/hookraft-3bhf</guid>
      <description>&lt;p&gt;React devs are still rewriting the same logic in every component…&lt;br&gt;
I built Hookraft to fix that&lt;br&gt;
Custom hooks. Cleaner code. Faster builds&lt;/p&gt;

&lt;p&gt;&lt;a href="https://hookraft.site" rel="noopener noreferrer"&gt;https://hookraft.site&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnimenq4zzl4wasqk3o9w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnimenq4zzl4wasqk3o9w.png" alt=" " width="800" height="410"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>programming</category>
      <category>opensource</category>
    </item>
    <item>
      <title>React custom hooks</title>
      <dc:creator>purposewalker</dc:creator>
      <pubDate>Sun, 29 Mar 2026 08:57:42 +0000</pubDate>
      <link>https://dev.to/purposewalks9/react-custom-hooks-2l47</link>
      <guid>https://dev.to/purposewalks9/react-custom-hooks-2l47</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd43nu7pyitlc1hgrbshu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd43nu7pyitlc1hgrbshu.png" alt=" " width="800" height="410"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Stop Rewriting the Same React Logic — I Built Hookraft to Fix This&lt;br&gt;
Every React project I've worked on has the same problem.&lt;br&gt;
You open a new component and before you write a single line of real logic, you're already typing this:&lt;br&gt;
tsxconst [loading, setLoading] = useState(false)&lt;br&gt;
const [error, setError] = useState(null)&lt;br&gt;
const [data, setData] = useState(null)&lt;br&gt;
Then the useEffect. Then the try/catch. Then the cleanup. Then you do it again in the next component. And the next project. And the next.&lt;br&gt;
I got tired of it. So I built Hookraft.&lt;/p&gt;

&lt;p&gt;What is Hookraft?&lt;br&gt;
Hookraft is a collection of composable React hooks that handle the logic side of your app — async flows, task queues, state history, and more.&lt;br&gt;
The idea is simple: instead of scattering useState and useEffect across your components, you use hooks that already know how to handle the hard parts.&lt;/p&gt;

&lt;p&gt;hookraft.site | github.com/purposewalks9/Hookraft&lt;/p&gt;

&lt;p&gt;The two hooks shipping today&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;useQueue — process tasks in sequence
Ever needed to send a bulk list of emails, upload multiple files, or process a list of items one by one?
Without Hookraft you're managing a queue manually — tracking which items are pending, which are processing, which failed, and wiring up concurrency yourself.
With useQueue:
tsximport { useQueue, Queue } from "@hookraft/usequeue"&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;function BulkEmailSender() {&lt;br&gt;
  const queue = useQueue({&lt;br&gt;
    onProcess: async (item) =&amp;gt; await sendEmail(item.email),&lt;br&gt;
    onSuccess: (item) =&amp;gt; console.log(&lt;code&gt;Sent to ${item.email}&lt;/code&gt;),&lt;br&gt;
    onError: (item, err) =&amp;gt; console.error(&lt;code&gt;Failed: ${item.email}&lt;/code&gt;),&lt;br&gt;
    onDone: () =&amp;gt; toast("All emails sent!"),&lt;br&gt;
    concurrency: 2,&lt;br&gt;
  })&lt;/p&gt;

&lt;p&gt;return (&lt;br&gt;
    &lt;/p&gt;
&lt;br&gt;
       queue.add({ email: "&lt;a href="mailto:a@example.com"&gt;a@example.com&lt;/a&gt;" })}&amp;gt;&lt;br&gt;
        Add Email&lt;br&gt;
      &lt;br&gt;
      &lt;br&gt;
        Start&lt;br&gt;
      &lt;br&gt;
      &lt;br&gt;
        Pause&lt;br&gt;
      
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  &amp;lt;p&amp;gt;Pending: {queue.pending.length}&amp;lt;/p&amp;gt;
  &amp;lt;p&amp;gt;Processing: {queue.processing.length}&amp;lt;/p&amp;gt;
  &amp;lt;p&amp;gt;Completed: {queue.completed.length}&amp;lt;/p&amp;gt;
  &amp;lt;p&amp;gt;Failed: {queue.failed.length}&amp;lt;/p&amp;gt;

  &amp;lt;Queue when={queue.status} fallback={&amp;lt;p&amp;gt;Queue is idle&amp;lt;/p&amp;gt;}&amp;gt;
    &amp;lt;p&amp;gt;Queue is active...&amp;lt;/p&amp;gt;
  &amp;lt;/Queue&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;)&lt;br&gt;
}&lt;br&gt;
You get:&lt;/p&gt;

&lt;p&gt;Full lifecycle control (idle → running → paused → done)&lt;br&gt;
Concurrency support&lt;br&gt;
Per-item success and error callbacks&lt;br&gt;
A Queue JSX component that renders based on status&lt;/p&gt;

&lt;p&gt;No manual state juggling. Just describe the flow.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;useHistory — undo/redo any state in one line
This one is my favourite.
Every app that lets users create or edit anything should have undo/redo. But building it from scratch means reducers, past/future stacks, careful immutability — it's a lot.
With useHistory:
tsximport { useHistory } from "@hookraft/usehistory"&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;function TextEditor() {&lt;br&gt;
  const {&lt;br&gt;
    state,&lt;br&gt;
    set,&lt;br&gt;
    undo,&lt;br&gt;
    redo,&lt;br&gt;
    canUndo,&lt;br&gt;
    canRedo,&lt;br&gt;
    jump,&lt;br&gt;
    history,&lt;br&gt;
    clear,&lt;br&gt;
  } = useHistory("", { limit: 100 })&lt;/p&gt;

&lt;p&gt;return (&lt;br&gt;
    &lt;/p&gt;
&lt;br&gt;
      
        value={state}&lt;br&gt;
        onChange={(e) =&amp;gt; set(e.target.value)}&lt;br&gt;
        placeholder="Start typing..."&lt;br&gt;
      /&amp;gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  &amp;lt;button onClick={undo} disabled={!canUndo}&amp;gt;Undo&amp;lt;/button&amp;gt;
  &amp;lt;button onClick={redo} disabled={!canRedo}&amp;gt;Redo&amp;lt;/button&amp;gt;
  &amp;lt;button onClick={clear}&amp;gt;Clear&amp;lt;/button&amp;gt;

  {/* Click any past entry to jump straight to it */}
  &amp;lt;ul&amp;gt;
    {history.map((entry, index) =&amp;gt; (
      &amp;lt;li key={index}&amp;gt;
        &amp;lt;button onClick={() =&amp;gt; jump(index)}&amp;gt;
          {entry || "(empty)"}
        &amp;lt;/button&amp;gt;
      &amp;lt;/li&amp;gt;
    ))}
  &amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;)&lt;br&gt;
}&lt;br&gt;
The jump(index) function is the secret weapon here. Instead of clicking undo 10 times, you can render a full history timeline and let users teleport to any point — like Google Docs version history or Figma's history panel.&lt;br&gt;
Works with any type — strings, objects, arrays, whatever your state is.&lt;/p&gt;

&lt;p&gt;The philosophy behind it&lt;br&gt;
Modern React apps are not just UI. They are systems of:&lt;/p&gt;

&lt;p&gt;Async operations&lt;br&gt;
State transitions&lt;br&gt;
Background tasks&lt;br&gt;
Error recovery&lt;/p&gt;

&lt;p&gt;Most developers solve these problems repeatedly with ad-hoc logic. Over time that creates fragile, hard-to-maintain codebases.&lt;br&gt;
Hookraft's goal is simple:&lt;/p&gt;

&lt;p&gt;Turn complex logic into readable, predictable primitives.&lt;/p&gt;

&lt;p&gt;Instead of stitching logic together, you define flows. Your components stay clean. Your logic stays structured.&lt;/p&gt;

&lt;p&gt;Installing&lt;br&gt;
bash# Queue hook&lt;br&gt;
pnpm add @hookraft/usequeue&lt;/p&gt;

&lt;h1&gt;
  
  
  History hook
&lt;/h1&gt;

&lt;p&gt;pnpm add @hookraft/usehistory&lt;br&gt;
Both packages are fully typed with TypeScript, work with React 19, and have zero UI opinions — use them with any component library or none at all.&lt;/p&gt;

&lt;p&gt;What's coming next&lt;br&gt;
Hookraft is actively being built. On the roadmap:&lt;/p&gt;

&lt;p&gt;useAsync — async function with full status tracking&lt;br&gt;
useRetry — auto-retry with backoff&lt;br&gt;
usePoll — interval-based polling with pause/resume&lt;br&gt;
useStepFlow — multi-step wizard flow&lt;br&gt;
useForm — form state and validation&lt;/p&gt;

&lt;p&gt;Try it out&lt;/p&gt;

&lt;p&gt;Site: hookraft.site&lt;br&gt;
GitHub: github.com/purposewalks9/Hookraft&lt;br&gt;
Twitter: @purpose_walker&lt;/p&gt;

&lt;p&gt;If you find it useful, a star on GitHub goes a long way. And if you have a hook idea or want to contribute, PRs are open.&lt;br&gt;
What logic do you find yourself rewriting the most in React? Drop it in the comments it might become the next Hookraft hook&lt;/p&gt;

</description>
      <category>react</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>typescript</category>
    </item>
  </channel>
</rss>
