Skip to content

Commit

Permalink
feat: adding useSignal for react libs
Browse files Browse the repository at this point in the history
  • Loading branch information
heyMP committed Jul 1, 2024
1 parent 15da6ec commit 9450d69
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 23 deletions.
42 changes: 21 additions & 21 deletions packages/react-sandbox/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,17 @@
import { useEffect, useState } from 'react'
import reactLogo from './assets/react.svg'
import viteLogo from '/vite.svg'
import './App.css'
import { Signal } from '@heymp/signals';
import { useSignal } from '@heymp/signals/react';

const counter = new Signal.State(0);
const nextCount = new Signal.Computed(() => counter.value + 1, [counter]);
const doneCounting = new Signal.Computed(() => counter.value > 4, [counter]);

function App() {
const [count, setCount] = useState(0)

useEffect(() => {
watchSignal();
}, []);

async function watchSignal() {
for await (const _ of counter) {
setCount(counter.value);
}
}
const [count] = useSignal(counter);
const [next] = useSignal(nextCount);
const [done] = useSignal(doneCounting);

return (
<>
Expand All @@ -31,15 +24,22 @@ function App() {
</a>
</div>
<h1>Vite + React</h1>
<div className="card">
<button onClick={() => counter.value++}>
count is {count}
</button>
<p>Your next count will be {nextCount.value}</p>
<p>
Edit <code>src/App.tsx</code> and save to test HMR
</p>
</div>
<div className="card">
{!done &&
<button onClick={() => counter.value++}>
count is {count}
</button>
}
{!done &&
<p>Your next count will be {next}</p>
}
{done &&
<p>You've reached the max count of {count}</p>
}
<p>
Edit <code>src/App.tsx</code> and save to test HMR
</p>
</div>
<p className="read-the-docs">
Click on the Vite and React logos to learn more
</p>
Expand Down
10 changes: 9 additions & 1 deletion packages/signals/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@
"types": "./src/lib/lit/decorators/watchSignal.d.ts",
"default": "./src/lib/lit/decorators/watchSignal.js"
},
"./lit/*": "./src/lib/lit/*"
"./lit/*": "./src/lib/lit/*",
"./react": {
"types": "./src/lib/react/useSignal.d.ts",
"default": "./src/lib/react/useSignal.js"
}
},
"files": [
"src/*{.d.ts,.js}"
Expand All @@ -29,5 +33,9 @@
"devDependencies": {
"tslib": "^2.6.2",
"typescript": "^5.2.2"
},
"peerDependencies": {
"@types/react": "^18.2.23",
"react": "^18.2.0"
}
}
2 changes: 1 addition & 1 deletion packages/signals/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export class SignalUpdatedEvent<T> extends Event {
}

export class State<T> extends EventTarget {
private _value: T;
_value: T;

/**
* Creates a new signal
Expand Down
18 changes: 18 additions & 0 deletions packages/signals/src/lib/react/useSignal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import type { State } from '../../index.js';
import {useEffect, useState} from 'react';

export function useSignal<T extends State<unknown>>(signal: T) {
const [value, setValue] = useState(signal.value);

useEffect(() => {
watchSignal();
}, []);

async function watchSignal() {
for await (const v of signal) {
setValue(v);
}
}

return [value as T extends State<infer U> ? U : never] as const;
}

0 comments on commit 9450d69

Please sign in to comment.