How can I pass data from an innermost child component upwards through an arbitrary amount of different parent components, having each parent component modify the data all the way up until the outermost parent renders it?
For example, suppose I have some math utilities like initial(num: number)
, add(amount: number, num: number)
, and subtract(amount: number, num: number)
that are used in vanilla js like:
const total = add( 2, subtract( 4, initial(10) ) )
console.log(total) // logs: 8 ie: 10 - 4 + 2
How can I create components to use these in a declarative way, like:
<Add amount={2}>
<Subtract amount={4}>
<Initial num={10} />
</Subtract>
</Add>
Which would output something like: <span>8</span>
I would like to be able to use an arbitrary amount of nesting between the different "modifier" components all nested around an initial "data setting" component. See REPL with the vanilla JS implementation: https://svelte.dev/repl/30ce69a25f1b46269e0a9918c84f36aa?version=4.2.0
I’ve tried using context and can’t quite get it to work.
3
Answers
Thanks to a very smart person on the Svelte Discord, I got a working and very elegant solution:
This is such an interesting problem.
This REPL shows how to accomplish this using Svelte’s data binding.
The idea is to expose the required input and calculated output as props, then databind the whole thing. This is not easy in any way, but does the job.
You’ll notice this has "V2" in its name. My "V1" tried to make use of slot props. It works as well, but it is wordier and I even needed the
tick()
function to synchronize things.To achieve the behavior you described, where data flows from an innermost child component upwards through multiple parent components, you can use React’s context API and React’s component composition. You can create a context that provides the necessary functions for performing mathematical operations and wrap your components in this context. Here’s a step-by-step guide on how to do this:
Create a Math Context:
1: First, create a context that will provide the math utility functions (initial, add, subtract).
2: Create Your Components:
Create components for Initial, Add, and Subtract that use the useMath hook to access the math utility functions.
Then
Then:
3: Use Your Components:
Now, you can use these components in a declarative way, just like in your example.
Now, when you render App, it will calculate the total by composing the Add, Subtract, and Initial components, and the result will be displayed in the div. Data flows from the innermost child component upwards through the parents, and each parent modifies the data as needed until the outermost parent renders it.