Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Push baobab Notes to root level? #20

Closed
bebraw opened this issue May 6, 2015 · 6 comments
Closed

Push baobab Notes to root level? #20

bebraw opened this issue May 6, 2015 · 6 comments

Comments

@bebraw
Copy link
Member

bebraw commented May 6, 2015

Possible structure (thanks to @gaearon):

lanesById: { // { laneId -> lane }
  1: { id: 1, name: 'Lane' },
  2: { id: 2, name: 'Other Lane' }
},
notesById: { // { noteId -> note }
  1: { id: 1, name: 'Note' },
  2: { id: 2, name: 'Other Note' },
  3: { id: 3, name: 'Yet Another Note' },
},
laneOrder: [2, 1], // [laneId*]
noteOrder: { // { laneId -> [noteId*] }
  1: [2, 1],
  2: [3]
}

I need to see if facets can be used to provide a nicer API and hide id stuff from components. I wonder if those are dynamic enough.

@christianalfoni
Copy link
Contributor

Hi @bebraw , I am working on this structure now. The problem with the above structure is that you can not do optimistic updates as you depend on IDs. What I have found to be a good solution is to use client side REFS and map them to data IDS. This article explains the concept: http://www.christianalfoni.com/articles/2015_05_18_Cerebral-developer-preview#complex-state-handling.

I also implemented this in our current project at my employer. This is the implementation:

var refs = [];
var ids: [];
var nextId = 0;

return {
  create: function(id) {
    var ref = refs[refs.length] = 'app_ref_' + nextRef++;
    if (arguments.length) {
      if (id && ids.indexOf(id) >= 0) {
        return refs[ids.indexOf(id)];
      }
      ids[ids.length] = id;
    } else {
      ids[ids.length] = null;
    }
    return ref;
  },
  update: function(ref, id) {
    if (ids.indexOf(id) >= 0) {
      throw new Error('The id to reference already exists. Make sure all ids are unique and that you update refs with ids.');
    }
    ids[refs.indexOf(ref)] = id;
    return ref;
  },
  get: function(id) {
    return refs[ids.indexOf(id)];
  },
  remove: function(idOrRef) {
    if (refs.indexOf(idOrRef) !== -1) {
      var index = refs.indexOf(idOrRef);
      refs.splice(index, 1);
      ids.splice(index, 1);
    } else if (ids.indexOf(idOrRef) !== -1) {
      var index = ids.indexOf(idOrRef);
      refs.splice(index, 1);
      ids.splice(index, 1);
    }
  }
};

When you grab data from the server you always convert them to client side refs, like:

ajax.get('/notes').succes(function () {
  var notesMap = notes.reduce(function (allNotes, note) {
    var ref = refs.create(note.id);
    allNotes[ref] = note;
    return allNotes;
  });
})

When you now do an optimistic update you can just do this:

var ref = refs.create();
var note = notes[ref] = {
  title: 'hey'
});
ajax.post('/notes', note).success(function (id) {
  refs.update(ref, id);
  note.id = id;
}); 

This of course requires all IDs to be unique on the server. Or you can add custom prefixes in the client.

What is also great about this is that you can create relations between data:

var note = {
  id: '123',
  authorId: '456'
};

note.author = users[refs.get(note.authorId)];

You do not have to traverse anything to find relations. You just have this ref/id mapping.

Kinda cool :-)

@bebraw
Copy link
Member Author

bebraw commented May 23, 2015

So essentially we would be implementing a little database engine of our own on client side. I like the idea.

What do you think of IndexedDB or PouchDB? Maybe it would make sense to use a library that already solves the issue for us and adapt to that?

@christianalfoni
Copy link
Contributor

Yeah, absolutely @bebraw. I have no experience with those solutions, but that might be a way to go. Currently I just have this referencing implementation and storing the data directly in the tree with the rest of the state. But it could absolutely be a powerful concept to store this stuff in a client side database. Hm, thanks for that input, got me thinking :-)

@bebraw
Copy link
Member Author

bebraw commented Jun 24, 2015

Ended up going with Alt all the way. Maybe I'll do a Baobab specific chapter one day to see how to port the app there.

@bebraw bebraw closed this as completed Jun 24, 2015
@gaearon
Copy link

gaearon commented Jun 24, 2015

@bebraw Want to try Redux? It's single state tree under the hood, but no cursors—looks very similar to Flux. Awesome devtools are coming too.

@bebraw
Copy link
Member Author

bebraw commented Jun 24, 2015

@gaearon Sure. I could devote a chapter (about 1500-2000 words) to it. I set up an issue (#58) for tracking this. No ETA but I'll keep an eye on Redux. 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants