Great write up, really looking forward to seeing the full Mantra guide.
As I’ve mentioned to you previously, I’m working on a command line tool for generating these project scaffoldings and templates called Space Kitty. I’m going to go through your guide and see what I can incorporate into the tool so that devs can just start coding and stop worrying about setting up their project architecture!
But, we don’t use states in React. That’s a hard rule. Anything you need to use inside a React component should come via props, unless it’s another component.
This throws me off a bit. I thought React’s way of doing things was to modify the state and let Render() do it’s thing. Now there are some camps saying that it’s better to have a ‘wrapper’ one layer up to pass raw props to components.
I see the merits of both, but I’m not sure why having wrappers is better. Can you elaborate on why you chose to do things this way?
Mainly separate UI components from the rest of the app. With containers(not context wrappers), we can work with multiple data sources and implement clean up logic.
If we do it manually, that’s a lot of work.
Now it we need to change the state manager (data layer), we don’t need to change our app at all. Just write a new container.
Here’s one thing I’m not super sure of - when you use containers, where do you store temporary state? I see how containers help you get server-side data, but what if you just need to represent an autocomplete filter, or a toggle for the view, or a modal, etc?
@msavin Hey dude!
I am so grateful for that forked song! I’ve heard it five months ago in the radio, in another country, and could not find the name. I rembered some parts (more or less correctly ), but were not able to find that song actually. I searched so much and now found it here at the forums, so much thanks. You the real MVP.
BTW: Mantra is long overdue. I hope that it will introduce the way to write our meteor applications - without struggling about the right architecture, libraries and technologies. I wait eagerly for Monday to see whether Mantra keeps its promises. Great work!
This is a great question, and something i’ve struggled with in the past. Using the autocomplete example… If you want to keep your view decoupled so that the input box, dropdown, etc… have no knowledge of your app (for re-usability), you can use this.state in the container and pass it down as props. You can create a function like updateDropdownStatus and pass that down as a prop as well. This works as long as you’re not passing it down too far, then it can get confusing as to where it originated from (then Redux is more simple in that case).
I just wanted to clarify this a bit, even though others have answered this as well.
First, I think it makes sense to look at why to do this in the first place:
**1. Easier mental model**
When the data changing happens somewhere else, it’s easier to think about what your view is doing. It can only have one paramater… props, so there are less possible variations of ‘what could have happened’ when debugging.
When the localstate / remote db fetching is in one place (a container) it makes it easier to pinpoint where data lives and how it might be triggered. In a package/component when all the state lives at the very top of it’s tree there are no doubts about where to look. In a large app, something like Redux means that all local state lives in one object tree.
When the actions (or verbs) are in once place… typically functions, you can also know where to jump to. For example if you are curious on how the data in props changed, you know to start with any functions the container provides… or if using Redux, what actions are imported for this.
Additionally with Redux if trapping a debugging in Actions is clear, you can always put a breakpoint in the reducer, which is simply a function that takes the old state and returns the new state… which should solve ‘how’ it got changed (via stacktraces).
**2. Easier testing**
If database calls and local state changes are somewhere else than that means you don’t have to stub out Meteor or other hard to test things. A component just using props is just like this first normal function:
// easy to test, no suprises
function addTwo(a, b) {
return a + b;
}
// hard to test, hidden surprise inside
function addTwo(a, b) {
Posts.update('id2', {$set: {time: Date.now()}})
return a + b;
}
3. Easier Re-Use
Most apps have very domain specific rules that only apply to this app. Perhaps it’s just something simple like triggering analytics or something complicated that determines what data to fetch. By isolating all of this into one place; anywhere really but a single view ‘container’ is good, and outside of the view altogether (like Redux) is even better (for re-use)!
For what it's worth some devs on React core have mentioned that they notice the need for Redux as leaky abstraction and are trying out ways to achieve the same thing without having to use Redux/flux.
This is really great @arunoda ! Thanks for setting up a standard architecture, I think this is very much needed and will greatly reduce the JS fatigue as we can now just go with one setup if maintainability is needed.
I’m sure you’ve thought of this but a file generator (perhaps Yo) would go a long way to init a basic app (sans training wheels) with wiring, and to scaffold out new pieces.
A set of Sublime snippets may also help add support and speedup development (I’ve found my Vim snippets have allowed me to use React+Redux and still beat the times it used to take to build in Blaze).
@arunoda It may to late for this, but have you checked on Cycle.js?. I think it’s already aimed to work as you intend to work with react (with a purely functional approach), cycle.js inputs are either props, events or components if I’m not wrong (I just bumped into cycle.js not too long ago).
Regardless of that, I think this is an awesome work, and is probably what this community needed! Great Job!
Yeah! Cycle is doing a great job. But Mantra is a completely different project.
Cycle introduce it’s own component system and so on. And even the DOM layer.
But we don’t. (And we don’t have resources either).
Mantra is a way to formalize on folder structure and where your code goes and so on.
Then, we’ll let some flexibility to choose whatever we want to use in the data layer.
(Still while following some rules)
And our intention is not to fix the JS fatigue problem, but just for Meteor.
Because Meteor solves a lot of JS fatigue issues.
Since Mantra will focus on using pure UI react components, what are your thoughts on utilizing packages already out there that may not conform to these standards? For example, https://github.com/callemall/material-ui has a ton of nice components built for react, but I their components are stateful. What do you suggest here? Wrap those components in containers? Rewrite them? Don’t use them?