Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Robert
Robert

Posted on • Edited on • Originally published atblog.robertbroersma.com

     

Stateful Styles With XState and Styled System

You've probably seen a button like this one before:

<Button>CoolButton</Button>
Enter fullscreen modeExit fullscreen mode

One that has options:

<Buttonsecondary>SecondaryCoolButton</Button>
Enter fullscreen modeExit fullscreen mode

Maybe even more options:

<Buttontertiary>TertiaryCoolButton</Button>
Enter fullscreen modeExit fullscreen mode

But what if I did this?

<Buttonsecondarytertiary>Secondary?CoolButton</Button>
Enter fullscreen modeExit fullscreen mode

That's probably not allowed. I guess we'll change the API to avoid that:

<Buttonvariant="secondary">SecondaryCoolButton</Button>
Enter fullscreen modeExit fullscreen mode

This is kind of a state machine! YourButton can only be in onevariant (state) at a time.

Here's what a parallel state machine (basically multiple independent state machines) would look like:

<Buttonvariant="secondary"mode="dark">DarkSecondaryCoolButton</Button>
Enter fullscreen modeExit fullscreen mode

I've found that these kind of style props work very well with logical state machines. Check out the following example of a... thing:

Visualization of a State Machine

It's a parallel state machine with 3 sub machines:

  • One machine that let's you change the shape:
    • From Circle to Square
    • From Square to Diamond
    • From Square to Circle
    • From Diamond to Square
  • One machine that let's you change the color:
    • From Red to Blue
    • From Blue to Green
    • From Green to Red
  • One machine that let's you change the size:
    • From Small to Big
    • From Big to Small

If we want to craft some stateful styles for this thing, we'd need a component with an API like this:

<Thingshape="circle|square|diamond"color="red|blue|green"size="small|big"/>
Enter fullscreen modeExit fullscreen mode

You can implement it however you like, but what I like to do is usestyled-system'svariant API, because it maps nicely to the state machines we defined:

importstyledfrom'styled-components'import{variant}from'styled-system'constThing=styled(variant({prop:'shape',variants:{square:{/** Make it square */},circle:{/** Make it circular */},diamond:{/** Make it a diamond */},},}),variant({prop:'color',// ...}),variant({prop:'size',// ...}))
Enter fullscreen modeExit fullscreen mode

(You can use it with either Emotion or Styled Components)

Now to wire it up to our state machine usingxstate and@xstate/react

functionApp(){const[state,send]=useMachine(shapeMachine);return<Shape{...state.value}/>}
Enter fullscreen modeExit fullscreen mode

Ta-da! A little explanation:
In case of a hierarchical or parallel state machine, ours being the latter,state.value contains an object representation of our current state (checkthe docs for more info). Our state could look something like this:

//state.value{shape:"circle",color:"red",size:"small"}
Enter fullscreen modeExit fullscreen mode

Which happens to look exactly like our component's prop interface! Of course you can also dothis if you want your code to be a bit more explicit and readable:

functionApp(){const[state,send]=useMachine(shapeMachine);const{shape,size,color}=state.valuereturn<Shapeshape={shape}size={size}color={color}/>}
Enter fullscreen modeExit fullscreen mode

Here's aCodeSandbox with a fully working example.

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

Robert is a developer from Amsterdam who likes to talk about himself in the third person.
  • Location
    Amsterdam
  • Education
    Bachelor of Creative Technology, Master of Game Studies
  • Joined

More fromRobert

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