Comments (6)
more mind dumps...
It would actually need to be closer to this:
cerebral.watch('authors', function(data [, uuid, path2...]) {
// ok, no data. We need to get it from server so add isLoading
if (!data) {
let data = {
$isLoading: true
};
// we have an extra keypath so we need to be more specific
if (uuid) {
data.id: uuid
cerebral.signals.missingAuthor(uuid);
return data
}
// else we make the basic call
cerebral.signals.missingAllAuthors();
return data
}
return data
})
// then it would cater for each use case
var author = cerebral.get('authors', uuid)
var authors = cerebral.get('authors')
from cerebral.
Hi @idream3 ,
You raise an important question here. What I value most of all is to keep the code readable and easy to compose in your head. Adding a concept of watch would make it harder to compose how the application works. You have your cerebral state, your maps and also this watcher. How they interoperate is just difficult I think, as they are very decoupled.
I do see your concern of keeping DRY code, but you could quite easily do something like:
var setOrGetAuthor = function (cerebral, id) {
let author = cerebral.get('authors')[id];
if (!author) {
author = {
id: id,
$isLoading: true
};
cerebral.signals.missingAuthor(id);
}
return author;
};
cerebral.map('visibleTodos', ['todos', 'authors'], function (cerebral, uuid) {
let todo = cerebral.get('todos')[uuid].toJS();
todo.author = setOrGetAuthor(cerebral , todo.authorId);
})
And you could just reuse that function across all mapping.
I think we need more experience before implementing a brand new concept at least, but thanks a lot for the input :-)
from cerebral.
Ok, I agree that another concept abstraction is probably not the way to go.
Your code above illustrates nicely how you could inline for a single use case and wrap into a generic function for multiple cases. I would be inclined to have a general file called getOrFetch.
And then:
cerebral.map('visibleTodos', ['todos', 'authors'], function (cerebral, uuid) {
let todo = cerebral.get('todos')[uuid].toJS();
todo.author = getOrFetch.author(cerebral , todo.authorId);
return todo
})
The benefit of leaving it how it is gives us developers more flexibility :)
This does, however, remind me of another concern I have about data fetching. Literally all of the data in my application is fetched from a server and I suspect this will be the case for most applications (or local storage etc...). Data fetching works well within Maps but how to fetch data for a single path elegantly?
Take this for example:
var state = {
projects: {},
users: {}
templates: {}
notes: {}
}
All data needs to be fetched from the server. In my current Flux implementation most of the requested data fetching is handled by the store if the data does not exist (exactly like the Map function above). You can do this because you define the get methods on the store like getProjects, getUsers etc...
But for single key paths in Cerebral how do you do this with out having a pseudo getter for each one:
Cerebral.Map('getProjects', ['projects'], (cerebral, state) => {
if (!state.projects) return getOrFetch.projects();
return state.projects
})
Hmmm, but then this wouldn't even work because you are concerned with the initial load of data and in this case 'getProjects' Map wouldn't even trigger because the 'projects' path will not fire a change when the (React) component is mounted.
Now then, I see two options as a start:
- add a signal into componentWillMount (initialize)
componentWillMount() {
if (!this.state.projects) this.signals.missingProjects()
if (!this.state.users) this.signals.missingUsers()
},
render() {
if (!this.state.projects || !this.state.users) return <Loading/>
}
But it seems to me that the components should just ask for the data and not be concerned about requesting for missing data.
Also the code above is something that should go into Higher-order components. Perhaps we implement something like Baobab-react. (create a separate issue?).
- Implement something akin to my first comment - a function that runs after 'getting' a path.
Cerebral.afterGet('projects', value => {
if (!value) signals.missingProjects()
return value
})
Or, perhaps we can use the Map here. The Map function runs when either of the paths have changed/update, maybe if the second paramter is a function it will run the Map function after the using the 'get' function.
Cerebral.Map('projects', value => {
if (!value) signals.missingProjects()
return value
})
Not sure if any of this feels like the right way to go about it... I will keep experimenting with this aspect.
from cerebral.
Hi @idream3 and again thanks for input :-)
In this scenario I would suggest this:
let getInitialData = function () {
return Promise.all([getProjects, getTemplates, getUsers]);
};
cerebral.signal('applicationRendered`, getInitialData, setInitialData);
And this signal would trigger on the componentDidMount
of the root component. This way you can reuse the getProjects etc. function on other signals. I am skeptic to creating too much automation as it is difficult to reason about when things trigger. I think it is an important concept in Cerebral that all state change is handled with a signal.
This actually got me to thinking:
cerebral.signal('applicationRendered`, [getProjects, getTemplates, getUsers], setInitialData);
It would be possible to indicate that these actions should run in parallell and when all are done, go to next action. What do you think?
Anyways, your suggestion on using map would also work.
from cerebral.
Great stuff, I like the parallel addition.
I actually think now that it does make sense for a component to send a signal on mount that it needs data if missing.
I am going to experiment with this in my higher order components and see how we go.
Thanks for your feedback :)
from cerebral.
Cool! I will just close this for now. Create a new issue if new questions related to this pops up :-)
from cerebral.
Related Issues (20)
- compute from computed from another computed does not work HOT 7
- Allow providers to have keys other than functions HOT 1
- What happened to mobx-state-tree HOT 4
- Change in computed state does not trigger reactions HOT 2
- A certain combination of feature usage causes forceUpdate() on an unmounted component HOT 1
- How to use cerebral in vue-router hooks? HOT 2
- reaction errors HOT 7
- module.signals is DEPRECATED but controller in @cerebral/mobx-state-tree can't provide sequences HOT 1
- Can't resolve nested value via moduleState HOT 2
- Docs test page spelling error HOT 2
- When using devtools, cannot change store state using string path. HOT 1
- codesandbox.io using wrong cerebral version. HOT 1
- Setting non-existent path in state works without devtools, throws error with devtools HOT 1
- Cerebral v4: Deprecated React lifecycle methods HOT 1
- function-tree Can't resolve './StopExecution' HOT 3
- Can't resolve nested value via moduleState (from computed) HOT 1
- Cerebral 5.2.0: inferno does render child before parent HOT 2
- access dotted keys HOT 1
- parallel does not work as expected HOT 1
- `addModule` doesn't initialize reactions
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from cerebral.