meiosis-setup
automatically sets up Meiosis with Nesting (explained in the Meiosis Documentation:
reference), so that you can call cell.nest
to get a
nested cell:
cell.nest('someProperty')
With TypeScript support, when entering a string within nest('')
, auto-suggest indicates valid
properties. Moreover, specifying an invalid property results in an error.
Once we have a nested cell, cell.state.x..
auto-suggested nested properties, as does
cell.update({ x: ... })
.
Try experimenting with the code below.
meiosis-setup
also provides nested components. This conveniently combines nesting of:
into components. Components can operate on their cell.state
without being "aware" of how their
state is nested within the application state.
Also, a component can be reused multiple times simply by nesting it again with a different property.
To specify nested components, use the nested
property of app
:
const app:MeiosisComponent<State> = {
nested: {
...
}
};
const cells = meiosisSetup<State>({ app });
Within nested
, specify properties on the application state where components will be nested. For
each property, specify an object with the same structure as an app
object, that is, of type
MeiosisComponent<YourNestedState>
, with initial
and/or services
. Moreover, you can also
specify a view
, in which case you can use the type MeiosisViewComponent<YourNestedState>
. For
example:
interface One {
counter: number;
}
interface Two {
duck: string;
}
interface State {
one: One,
two: Two
}
const oneComponent: MeiosisComponent<One> = {
initial: {
counter: 0
},
services: [...]
};
const twoComponent: MeiosisViewComponent<Two> = {
initial: {
duck: 'yellow'
},
view: (cell) => ...
};
const app: MeiosisComponent<State> = {
nested: {
one: oneComponent,
two: twoComponent
}
}
In the example above, the initial state will be:
{
one: {
counter: 0
},
two: {
duck: 'yellow'
}
}
For the onchange
and run
functions of the services in oneComponent
:
{
onchange: (state) => ...
run: (cell) => ...
}
The state
passed the onchange
function will be
{
counter: 0
}
And cell.nest('one')
will be passed to the run
function.
To call the view
function of oneComponent
, use the following code from the parent view:
cell.nested.one.view(cell)
the parent view. This will automatically pass cell.nest('one')
to the view
function of
oneComponent
.
If you need to pass more parameters to the view, add them and they will be passed along. For example:
cell.nested.one.view(cell, cell.state.loggedInUser)
The first parameter, cell
, will pass the nested cell to the view. If we also need data from
the parent state, we can pass it in the additional parameters, as shown above.
Besides passing parent state to a nested component, we may sometimes need to update a parent state property from a nested component.
Let's say we have a component that is nested within login
, and we want to update the parent state
by setting the loggedInUser
property using the onLogin
action below:
const actions = {
onLogin: (cell: MeiosisCell<State>, loggedInUser: string): void => {
cell.update({ loggedInUser });
}
};
Again we can simply pass an additional property to the view, this time passing a function that calls
actions.onLogin
:
cell.nested.login.view(cell,
(loggedInUser: string) => actions.onLogin(cell, loggedInUser))
The nested login
view can then get onLogin
as a parameter:
const login: MeiosisViewComponent<Login> = {
view: (cell, onLogin: (username: string) => void) => ...
};
The view can then call onLogin
at the appropriate time, passing the logged in user.
Finally, note that nested components can in turn have a nested
property and themselves use nested
components. Thus you can nest components at deeper levels within your application.
Below is an example of using nested components.
Notice how the login
and data
components can focus on their state without being "aware" of where
their state is nested within the application state.
Also note how the application view can call nested views with view(cell)
, which will automatically
pass the nested cell to the view.
The login
component shows how to update the parent state by passing an additional callback
parameter that calls `actions.onLogin.
The data
component exemplifies passing parent state to the component, in this case the logged in
user.
Finally, you can see that the data
component is reused as-is simply by nesting it with different
properties, data1
and data2
.