This PR is a refactor requested in Issue #29 in order to more efficiently manage shared state across components. This ticket was a large endeavor, I am not certain if I could have broken this down into more manageable tickets. It was one of those things that falls apart until it all comes back together at the end. This definitely hammers in the importance of planning state management from the get-go and not waiting until later to change state management techniques if you suspect something beyond useState is needed.
On the plus-side, Zustand is incredible, really dried things up in terms of prop-drilling, and was an amazing new tool to learn. I will definitely be using it again in the future.
Changes
There are so many changes on this one that I'll just summarize the general changes.
Restructured the config file into groups and settings to match the App's handling of the two separately. This should also make it easy to assemble and export the config into a JSON file from state in the future.
Created a useSettingsStore that is intended to hold customization settings the user has set.
Created a useGroupStore that is intended to manage everything related to the dial groups.
Created a useRenderStore that is intended to hold flags that aid in UI/UX interaction between distant components.
Zustand has an awesome persist integration that allows easy storage of state values in localStorage or another Storage API-compliant service.
Thinking about values that need to be "rehydrated" or not led to the creation of the useRenderStore which contains only session-related flags that shouldn't persist.
There was also a very interesting problem involving how to identify whether the state was persisted from localStorage or not. It took a lot of tinkering but I was able to use the onRehydrateStorage to check if the relevant key was in localStorage, then after the rehydration attempt I could set a loadedFromStorage flag to know for certain if anything had persisted. I may not need this feature in the future but I'm still a little dependent on an existing config so I need this to trigger an alert to receive a new configUrl for the time being.
Zustand's getState() for simply retrieving a value (including setting functions) from a store is very interesting and helped in the two cases where I needed to read a state value or call a setting function but didn't want to become reactive to any changes in that state. Super handy and I'm sure I'll get myself in trouble with it somehow.
Summary
This PR is a refactor requested in Issue #29 in order to more efficiently manage shared state across components. This ticket was a large endeavor, I am not certain if I could have broken this down into more manageable tickets. It was one of those things that falls apart until it all comes back together at the end. This definitely hammers in the importance of planning state management from the get-go and not waiting until later to change state management techniques if you suspect something beyond
useState
is needed.On the plus-side, Zustand is incredible, really dried things up in terms of prop-drilling, and was an amazing new tool to learn. I will definitely be using it again in the future.
Changes
There are so many changes on this one that I'll just summarize the general changes.
groups
andsettings
to match the App's handling of the two separately. This should also make it easy to assemble and export the config into a JSON file from state in the future.useSettingsStore
that is intended to hold customization settings the user has set.useGroupStore
that is intended to manage everything related to the dial groups.useRenderStore
that is intended to hold flags that aid in UI/UX interaction between distant components.persist
integration that allows easy storage of state values inlocalStorage
or another Storage API-compliant service.useRenderStore
which contains only session-related flags that shouldn't persist.localStorage
or not. It took a lot of tinkering but I was able to use theonRehydrateStorage
to check if the relevant key was inlocalStorage
, then after the rehydration attempt I could set aloadedFromStorage
flag to know for certain if anything had persisted. I may not need this feature in the future but I'm still a little dependent on an existing config so I need this to trigger an alert to receive a newconfigUrl
for the time being.getState()
for simply retrieving a value (including setting functions) from a store is very interesting and helped in the two cases where I needed to read a state value or call a setting function but didn't want to become reactive to any changes in that state. Super handy and I'm sure I'll get myself in trouble with it somehow.