What are canonical patterns to separate UI from domain logic in SolidJS?
I am developing an app that helps guitarists to learn notes. Users learn notes by exercising. The exercise asks to play a note, listens to the audio on mic, and gives feedback and further instructions.
I would like to separate domain logic from presentation to reach following objectives:
1) Test domain logic separately as it is relatively complex ( music theory, web audio, learning management )
2) Allow to swap different visual components. For instance I want to A/B test what visual components work better for learners hence I don't want to re-implement domain logic for each. In addition users might have own preferences about appearance. So the same domain logic should be able to work with different appearance.
3) Let devs work more efficiently - it's likely there will be specialist in CSS, UI, who will be working closely with a designer to iterate over appearance of the exercise across all it possible states. When doing so it would be great to pass a simple prop to show how exercise would look like.
What are the canonical patterns to achieve the mentioned objectives apart from using Context?
So far I came up with a decent, in my opinion approach, but would like a review:
1)
Exercise.jsx
- component concerned only with presentation - it contains JSX, styling and simple presentation logic. Exercise state readers and callbacks are passed as props.
2) createExercise.js
- this component handles state, exercise flow, logic, interfaces with WebAudio components and exposes signal readers and functions which Exercise.jsx
then uses.
3) A helper function withState
that allows to combine these 2 in a decoupled way. So that I could easily swap presentation without touching createExercise.js
You can check this gist for detailed example: https://gist.github.com/vasiliy-pdk/bc8d7c8f621516d9e2c52ac6146b4002
Is it The Right Way or there's better approach?Gist
Separate presentation from domain logic in SolidJS
Separate presentation from domain logic in SolidJS - shortenedExample.jsx
1 Reply
This is usually how I like to write more complicated components. Maybe skipping the 3) step because
<Search state={search_state} />
is simpler. Just an interface.