React
Integrating superstate with React is easy.
First you have to install @superstate/react
:
- npm
- yarn
npm install @superstate/react
yarn add @superstate/react
Then you'll be able to import the useSuperState
hook:
import { superstate } from '@superstate/core' import { useSuperState } from '@superstate/react' const count = superstate(0) export default function App() { useSuperState(count) return ( <div> Count is <strong>{count.now()}</strong><br/> <button onClick={() => count.set(prev => prev - 1)}>-</button> <button onClick={() => count.set(prev => prev + 1)}>+</button> </div> ) }
Targeting specific state version
By default, the useSuperState
hook will re-render your React component whenever either now
or draft
change.
However, sometimes you want to monitor only changes made to the draft
instead. To do so, all you have to do is
specifying draft
as a useSuperState
target:
import { superstate } from '@superstate/core' import { useSuperState } from '@superstate/react' const count = superstate(0) export default function App() { useSuperState(count, { target: 'draft' }) // this line! return ( <div> <button onClick={() => count.sketch(prev => prev - 1)}>-</button> <button onClick={() => count.sketch(prev => prev + 1)}>+</button> {typeof count.draft() !== 'undefined' && <section> Count's draft is: <strong>{count.draft()}</strong><br/> </section> } </div> ) }
If you want to target only now
version instead of both now
and draft
, just pass now
to target
.
Smart re-renders
It may sound dangerous to always re-render your component whenever a state changes, but don't worryโa re-render will only occur when changes are broadcasted, and changes are only broadcasted when the new state is actually different from the previous state.
Meaning that:
const count = superstate(0)
count.publish(5) // will trigger a re-render
count.publish(5) // will NOT trigger a re-render
count.publish(5) // will NOT trigger a re-render
count.publish(prev => prev) // will NOT trigger a re-render
count.publish(prev => prev + 1) // will trigger a re-render
const user = superstate({ name: 'John' })
user.publish(prev => prev) // will NOT trigger a re-render
user.publish(prev => ({ name: 'Doe' })) // will trigger a re-render
Currently, custom logic to trigger broadcasts/re-render is not supported.
Components rendering twice
If your component is rendering twice upon a superstate state change, it may be because of React's <StrictMode />
.
Just to make sure, unwrap your app from <StrictMode />
and try changing the state again.
If the problem went away, put your <StrictMode />
back and don't worryโthis doubled re-render is only happening in development mode and it's intentional (learn more);
otherwise, file an issue on GitHub.