What you need is a new abstraction.
Simply pulling out common bits of functionality ends up creating a mess. You need to find a brand new way of looking at your problem that enables you to extract the common functionality without producing a mess.
That's easier said than done!
For this particular case, a better idea is to split the logic of updating the dom from the logic of updating the state. Something like this:
function updateApp(updater) {
// fetch javascript object representing current state
var currentState = JSON.parse(sessionStorage.getItem("appState"));
// allow the passed in function to update that state
updater(currentState);
// save the state
sessionStorage.setItem("appState", JSON.stringify(currentState));
// update the user interface.
// the vhtml function update the #item-list to correspond
// to the html described by renderItems
$('#item-list').vhtml(renderItems(state));
}
// this function returns a data structure that describes the html that should
// be rendered.
function renderItems(state) {
return h("div",
state.items.map((item) => h("div.item", {data_id: item.id},
"Price: " + item.price * item.qty)));
}
// when you want to modify the state, do it through the updateState
// function. Here we have the relatively straightforward task of
// just tweaking the data structure holding the state to include
// the extra item.
$(".add_item").click(function() {
item_id = $(this).data("id")
updateState(function(state) {
state.items.push({
id: item_id
});
})
}
This new abstract changes the way you think about your code. Before, you had to worry about all the pieces of DOM that needed to be updated. Now, split the task into two:
- For your event functions, just update the state object in response to the action
- For the render function, just return the correct DOM nodes for the current state.
Now you simply don't need to write the code that figures out the correct changes to make to the DOM. That's handled for you. Hopefully, you can see that if you add more functions that change the dom you won't have to add a lot of complexity to handle all those cases. It will just work.
You may think it would be inefficient to simply rebuild the DOM each time for the render function. Yes, it would be. But there are a number of virtual dom libraries that make this efficient. It may or may not be worth adding to your project.
Whatever the merits to your particular case, this is the general solution to your problem: find a better way to divide your problem. The reason that it hasn't worked to build more generic functions for you is that you haven't found the ideal way to divide your task.