Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Cover image for A good reason to use React18: useSyncExternalStore
priolo
priolo

Posted on

     

A good reason to use React18: useSyncExternalStore

Let's consider a simple ToDo
This is what your colleague left you as a gift 💩 before going on holiday:

codesandbox

Inindex.js there is a mess of functions within components passed between components that call other functions.
And if it were a real project it would be MUCH MUCH worse

because the COMPONENT TREE isdeeper
and the nesting of COMPONENTs multiplies the complexity!

Let's create a STORE

Let us try to extrapolate the LOGIC and STATUS from the COMPONENTs to put it into a STORE.

constmyStore={callbacks:newSet(),subscribe:(callback)=>{myStore.callbacks.add(callback)return()=>myStore.callbacks.delete(callback)},getSnapshot:()=>myStore.state,changeState:(newState)=>{myStore.state=newStatemyStore.callbacks.forEach(cb=>cb())},}
Enter fullscreen modeExit fullscreen mode

codesandbox

It is a generic implementation of a STORE usinguseSyncExternalStore
the new React18 hook (but it can also be done with React17!).
therefore:

  • subscribeStores a callback to be called when the STATE of the STORE is changed
  • getSnapshotReturns the current STATE
  • changeStateIt is convenient to exchange one STATE for another STATE.Remember that a STATE is immutable!And notify all registeredcallbacks of the change

Enter the STATE

constmyStore={...state:{todos:[{desc:"init value"},],todoInEdit:{desc:""},},...}
Enter fullscreen modeExit fullscreen mode

codesandbox

It is a picture of what our VIEW, in this case the ToDo app, should look like.
A STATE represents one and only one view of the VIEW.

Enter the MUTATORS

constmyStore={...setTodos:todos=>myStore.changeState({...myStore.state,todos}),setTodoInEditProp:prop=>myStore.changeState({...myStore.state,todoInEdit:{...myStore.state.todoInEdit,...prop}}),...}
Enter fullscreen modeExit fullscreen mode

codesandbox

They simply execute thechangeState by passing it the modified STATE.
Consequently, they will notify the changes to the COMPONENTS.
(as said before)

Let's add the ACTIONS

constmyStore={...deleteTodo:(index)=>{constnewTodos=myStore.state.todos.filter((_,i)=>i!==index)myStore.setTodos(newTodos)},addTodoInEdit:()=>{constnewTodos=[...myStore.state.todos,myStore.state.todoInEdit]myStore.setTodos(newTodos)myStore.setTodoInEditProp({desc:""})},...}
Enter fullscreen modeExit fullscreen mode

codesandbox

Let's update the VIEW

functionApp(){return(<div><List/><Form/></div>);}functionList(){conststate=useSyncExternalStore(store.subscribe,store.getSnapshot)return(<ul>{state.todos.map((td,index)=>(<li>{td.desc}<buttononClick={_=>store.deleteTodo(index)}>                    Delete</button></li>))}</ul>)}functionForm(){conststate=useSyncExternalStore(store.subscribe,store.getSnapshot)consthandleChange=e=>store.setTodoInEditProp({desc:e.target.value})consthandleClickAdd=_=>store.addTodoInEdit()return(<div><inputvalue={state.todoInEdit.desc}onChange={handleChange}/><buttononClick={handleClickAdd}>Add</button></div>)}
Enter fullscreen modeExit fullscreen mode

codesandbox

The STORE is responsible for managing the LOGIC and the STATE
the VIEW simply synchronises with the STORE

The COMPONENTS are more readable

and can be moved without problems.
For example,List can be put inside another component without changing anything
because it is no longer "dependent" on its PARENT
In factList has no properties

this also makes unit-testing easier.

In short, if I have to change the behavior I have to look at the STOREs.
If I have to change the display I will have to act on the COMPONENTS

Jon

There are many libraries in React (as usual) that allow STATE management.
Of course I made one 😃
In my opinion, compared to the others, it allows

1) to see perfectly how it works under the hood. NO MAGIC
2) is super light
3) does only this, and nothing else

If you want, check it outhere

Top comments(0)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

  • Location
    Italy
  • Joined

More frompriolo

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp