From Vuex to Apollo:
GitLab journey
+
=
❤️
+
=
?
Natalia Tepluhina
Senior Frontend Engineer
Core Team Member
Google Dev Expert
@N_Tepluhina
+
@N_Tepluhina
@N_Tepluhina
Vuex
export default () => ({
isLoading: true,
addedLines: null,
removedLines: null,
endpoint: '',
basePath: '',
commit: null,
startVersion: null,
diffFiles: [],
mergeRequestDiffs: [],
mergeRequestDiff: null,
diffViewType: viewTypeFromQueryString || viewTypeFromCookie || defaultViewType,
tree: [],
treeEntries: {},
showTreeList: true,
currentDiffFileId: '',
projectPath: '',
commentForms: [],
highlightedRow: null,
renderTreeList: true,
showWhitespace: true,
fileFinderVisible: false,
dismissEndpoint: '',
showSuggestPopover: true,
});
@N_Tepluhina
@N_Tepluhina
Dispatch an action
Trigger
REST API call
Success?
Commit 'success' mutation
State changed
Commit
'error' mutation
Yes
No
@N_Tepluhina
@N_Tepluhina
@N_Tepluhina
Handling API responses
@N_Tepluhina
Send query
Success / error
State changed
Queries
@N_Tepluhina
Success / error
State changed
Mutations
Trigger
mutation
Update cache
@N_Tepluhina
Local state* = Apollo Cache
* - (everything is Apollo Cache)
@N_Tepluhina
const el = document.getElementById('js-design-management');
const { issueIid, projectPath } = el.dataset;
apolloProvider.clients.defaultClient.cache.writeData({
data: {
projectPath,
issueIid,
},
});
Setting initial local state
@N_Tepluhina
Query data from local cache like we query it from API
@N_Tepluhina
query projectFullPath {
projectPath
issueIid
}
"Normal" query...
@N_Tepluhina
query projectFullPath @client {
projectPath
issueIid
}
...vs "local" query
@N_Tepluhina
Vuex getters
export const getCurrentDesign = state => designId =>
state.designs.find(design => design.id === designId);
@N_Tepluhina
Local query + resolver
query getDesign($id: String!) {
design(id: $id) @client {
...DesignListItem
}
}
@N_Tepluhina
Local query + resolver
Query: {
design(ctx, { id }, { cache, client }) {
return client
.query({
query: projectQuery,
})
.then(({ data }) => {
const edge = data.project.issue.designs.designs.edges.find(
({ node }) => node.filename === id,
);
return edge.node;
})
},
},
@N_Tepluhina
Vuex action + mutation
export const toggleFileFinder = ({ commit }, visible) => {
commit(types.TOGGLE_FILE_FINDER_VISIBLE, visible);
};
...
[types.TOGGLE_FILE_FINDER_VISIBLE](state, visible) {
state.fileFinderVisible = visible;
},
@N_Tepluhina
Local mutation + resolver
mutation toggleFileFinder($visible: Boolean!) {
toggleFileFinder($visible: Boolean!) @client
}
Mutation: {
checkItem: (_, { visible }, { cache }) => {
const data = cache.readQuery({ query: fileFinder });
data.fileFinder.visible = visible;
cache.writeQuery({ query: fileFinder, data });
},
@N_Tepluhina
Vuex | Apollo |
---|---|
Mapped state | Local query |
Getters | Local query + resolver |
Actions +mutations | Local mutation + resolver |
@N_Tepluhina
Cons
-
verbosity of local resolvers
-
tests coverage
-
lack of best practices
-
cognitive load for developers
@N_Tepluhina
Thank you!
Apollo State Management
By Natalia Tepluhina
Apollo State Management
- 1,044