Closed hadihammurabi closed 3 years ago
@hadihammurabi for internal component state you can use a closure, e.g.:
const closure = () => {
let count = 0
return {
view: () =>
m('div',
m('h1', `Count: ${count}`),
m('button', {onclick: () => count++}, "+"),
m('button', {onclick: () => count--}, "-")
)
}
}
@osban How about global state?
@hadihammurabi Mithril does not really have a specific opinion of how to manage state in general, so it's up to you to do what makes the most sense to you.
So, the question becomes something like "how do I pass data to components", which is discussed in the docs using typical parameters here: https://mithril.js.org/components.html#passing-data-to-components - however, you can of course use any variable that is in scope, either being globally available in the window, or imported into the file that you're programming. Because of Mithril's autoredraw system, user interaction updates to variables will usually "just work", but if you have other asynchronous updates, you will probably need to use m.redraw
here and there to make sure that the view is updated at the proper times.
Essentially, if you'd like to use any particular framwork like redux/saga/mobx/immer/flyd etc. it's mostly a question of exposing data to the components that you write, and depending on how the data is updated making sure that the views are also updated with m.redraw
as required.
Mithril also has a streams-implementation that can be used unless you already have experience with or even an existing state management system in place https://mithril.js.org/stream.html - but depending on your actual case even this might be more than you actually need.
You might want to browse through some available code snippets in https://github.com/orbitbot/awesome-mithril and https://how-to-mithril.js.org , as well as read/skim through the documentation at https://mithril.js.org.
Drop by the chat at https://gitter.im/mithriljs/mithril.js if you have specific questions/problems, since this is a large topic and not really all that Mithril-specific outside of the integrations outlined above.
@hadihammurabi when more components need access to the same state, global state can be used, which can be a simple POJO. Other options are also possible, as @orbitbot has explained.
I think this is @porsager's Mitosis, a tweak of @foxdonut's Meiosis State Management pattern. Just sharing this in here for posteriority.
const State = () => ({ count: 0 });
const Actions = state => ({
increment: () => state.count += 1,
decrement: () => state.count -= 1
});
const state = State();
const actions = Actions(state);
const Counter = {
view: ({ attrs: { state, actions } }) =>
m('div',
m('h1', 'Counter'),
m('p', state.count),
m('button', { onclick: actions.increment }, '+'),
m('button', { onclick: actions.decrement }, '-')
)
};
m.mount(document.body, {
view: () => m(Counter, { state, actions })
});
I think this is @porsager's Mitosis, a tweak of @foxdonut's Meiosis State Management pattern. Just sharing this in here for posteriority.
const State = () => ({ count: 0 }); const Actions = state => ({ increment: () => state.count += 1, decrement: () => state.count -= 1 }); const state = State(); const actions = Actions(state); const Counter = { view: ({ attrs: { state, actions } }) => m('div', m('h1', 'Counter'), m('p', state.count), m('button', { onclick: actions.increment }, '+'), m('button', { onclick: actions.decrement }, '-') ) }; m.mount(document.body, { view: () => m(Counter, { state, actions }) });
Thanks a lot!
Here is my JSX version for anyone who's stuck like I was
export const state = { count: 0 }
export const actions = {
increment: () => state.count += 1,
decrement: () => state.count -= 1
}
export const Counter = {
view: () => {
return (
<div>
<div>{state.count}</div>
<button onclick={actions.increment}>+</button>
<button onclick={actions.decrement}>-</button>
</div>
)
}
}
m.mount(document.getElementById("app"), {
view: () => <Counter></Counter>
})
How MithrilJS handle state of component?