Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to deal with nested state in apollo-link-state (similar to Redux's combineReducers)

If we look at the todos example, imagine that the application had multiple views (a TodoList page and another page).

So instead of "todos" directly referring to an array of todo items, at the top level of the state/store/cache it would actually just be a view with some of its own state.

Inside that view, we'd define the list of todo items and visibility filter - so the state/store/cache would NOT be looking like this:

{
  todos: [TodoItem]
  0:▾TodoItem:0
  completed: false
  id: 0
  text: "hh"
  visibilityFilter: "SHOW_ALL"
}

but as:

{ 
  scenes: {
    TodoList: {
      todos: [TodoItem]
      0:▾TodoItem:0
      completed: false
      id: 0
      text: "hh"
      visibilityFilter: "SHOW_ALL"
    },
    SomeOtherView: { /* other state */}
  }
}

It might even be isolated in its own data "module", like proposed here: https://medium.com/@alexmngn/how-to-use-redux-on-highly-scalable-javascript-applications-4e4b8cb5ef38 :

{ 
  scenes: {
    TodoList: {
      data: {
        todos: [TodoItem]
        0:▾TodoItem:0
        completed: false
        id: 0
        text: "hh"
      }
      visibilityFilter: "SHOW_ALL"
    },
    SomeOtherView: { /* other state */}
  }
}

application wide state would be store a level further out:

{
  // App global state lives as long as the app
  data: { /* App global relevant data */},
  someglobalstate: true, 
  scenes: {
    TodoList: { // "view state" lives as long as the view is active, and resets when navigated away from
      data: {
        todos: [TodoItem]
        0:▾TodoItem:0
        completed: false
        id: 0
        text: "migrate from redux to apollo-link-state"
      }
      visibilityFilter: "SHOW_ALL"
    },
    SomeOtherView: { /* other state */}
  }
}

We can achieve this easily with reducer composition in Redux, like this:

Starting from the inside: todos would have its own reducer which is combined in the data reducer, which is combined in the TodoList reducer with the key "data". The TodoList reducer would then again be combined in the scenes reducer and so forth up to the top, to make the nested state reflect the folder structure of the project.

But how would something like this be possible with apollo-link-state and resolvers without defining everything in a single "TodoList" resolver?

Additional question:

How would you clear the TodoList state once you navigate away? In Redux I guess you'd trigger an actions which would clear the given slice of the state.

P.S.

"apollo-link-state" & "apollo-link" tags are missing in stackoverflow. Maybe someone with rep > 1500 could add those?

like image 540
Soren Avatar asked Jan 02 '18 16:01

Soren


1 Answers

I have the same question. It seems that apollo-link-state expect a function at the top level of the resolver, so it is not possible to created nested structures as it would be in a Redux store.

As the introduction post says, though, it is expected that apollo-link-state would manage only roughly 20% of the state, the rest being fetched data from the GraphQL Server. So it might not make sense to split the local state as much as it makes senses to split a Redux store.

For now, I've settled on using prefixes for the main domains of the local state.

like image 50
Christophe Noël Avatar answered Nov 03 '22 21:11

Christophe Noël