What is a good way in React to deal with web forms with interdependent state, where changes in one input element cause cascading, dynamic changes in other elements?
Here's one example: I'm building a React form with four react-select components (let's call them A/B/C/D) and I'm trying to wire them up so that changes in one Select will cause changes in one or more of the others.
For example:
A, then reload the data in B. Try to maintain a similar selected option in B after the data is loaded. "Similar" means that if the new data contains an option with the same name, even if the underlying object is different, then keep that named option selected in B. Otherwise clear B's selection.B, then load C with a filtered subset of A's data, with the selected option of B controlling how the filtering works. Like above, if the new contents of C have a same-named option (even if the underlying data is different) then keep it selected. Otherwise, clear the selection in C.A and there's a selection in B, and if nothing is currently selected in C, then make the selection of C match the selected option of A.C (including if it's changed via changes cascading from A or B!) then refresh the contents of D, but like above try to keep the same-named label selected in D, even if the data underneath it has changed. Otherwise select the first option in the newly-populated D.I'm fairly comfortable building React apps with controlled components where the state machine is simple and dependencies are clear. But in this case, the dependency tree is complicated!
I've already pushed my state (contents of A-D and their selected options) up to a container component.
But I'm finding that doing this is like pulling a thread on a sweater. After I moved the state up to the top, now I need domain-specific logic to determine what to do with the state, and that logic (e.g. getting data & translating it into user-visible UI in each component) is currently encapsulated in lower-level components. For example, component A is responsible for loading A's data, B loads B's data, etc.
Do I also need to move that logic up to the top-level component? Or is there some other pattern that I should consider for this kind of complex, interdependent UI state?
If it matters, I'm using plain React without any context, state-management or forms libraries, etc. Just useState and react-select.
This can be solved by holding a component with the main state and logic for your react-select components. These react-select should be siblings of the same parent:
MyStateHolderComponent
|
| Holds state
| const [someState, setSomeState] =useState(null)
|
+-- component A (on select, updates sameState from parent, you can drill a function to component A to do so)
+-- component B (receives someState as prop. Every time component A updates, it will be re rendered with the new prop)
+-- component C
+-- component D
At the same time, component A, B, C, D might have a state on their own. You can handle this architecture by drilling down callbacks that update the parent state, or is use the Context Api.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With