import React, { useEffect, useRef } from 'react'
import { AnimateRerender } from './AnimateRerender'
import { actions, fetchUsers, getState, reset, useStore } from './store'
const CurrentTime = () => {
const { currentTime } = useStore()
{currentTime.toLocaleTimeString()}
const { upperCaseMessage } = useStore()
return <AnimateRerender>Uppercased message: {upperCaseMessage}</AnimateRerender>
const MessageInput = () => {
const { setMessage } = useStore()
defaultValue={getState().message}
onChange={(e) => setMessage(e.target.value)}
Message is printed in uppercase using derived hook.<br />
Updates are done using <span>actions</span> so Input component won't re-render!
const CounterDisplay = () => {
const { counter } = useStore()
const { setCounter } = useStore()
<div className="buttons-container">
<button onClick={() => setCounter(prev => prev - 1)}>Decrement</button>
<button onClick={() => setCounter(prev => prev + 1)}>Increment</button>
<button onClick={() => reset('counter')}>Reset counter</button>
Counter is incremented and decremented using <span>actions</span>,<br />and can be reset using <span>reset</span> function.
const UsersList = () => {
const { users } = useStore()
const listRef = useRef<HTMLDivElement>(null)
listRef.current?.scrollTo({
top: listRef.current.scrollHeight,
const { setUsers } = useStore()
const fetchMoreUsers = async () => {
const users = await fetchUsers()
setUsers(prev => [...prev, ...users])
<button onClick={fetchMoreUsers}>
Users are fetched from an API<br />and appended to the list asynchronously.
export const App = () => {
const interval = setInterval(() => {
actions.setCurrentTime(new Date())
return () => clearInterval(interval)
<p>The timer is updating every second using a setInterval.</p>