How to refer to the current state in FP?

Viewed 111

I've already asked that question but my explanation was pretty bad, so I decided to ask again with a better explanation and with actual code (I'll ask moderators to delete one of the posts). So let's consider the problem.

Following snippet represents rendering notes from array. However, during the adding note part, I mutate a state. So the question is: how can I add a new note in notes array without mutating? In other words, I want to remove replaceNotes and remain the same functionality. I know that it's possible to add notes without array at all, but I do need to update array with notes in due to the future reference. The ting is, in my original application I've got lists with notes, and while I switch between lists, I should get rendered notes that relies to the list I switch on. That's why I should keep the reference to notes array.

At the same time I'm wondering, would it be okay, if I just store notes in localStorage and then take notes from that data? Is it a good practice in functional programming?

const button = document.getElementById('button');
const notesContainer = document.querySelector('.notes');

const pipe = (f, g) => (...args) => f(g(...args));

let notes = [];

const createNote = (...fns) => fns.reduceRight(pipe);

const handleEvent = () =>
   createNote(gatherContent, renderContent, replaceNotes)(notes);

function gatherContent(notes) {
   const name = prompt('How do you want to name a note?');

   return [...notes, { name }];
}

function renderContent(notes) {
   function render(note) {
      const noteEl = document.createElement('div');
      noteEl.innerHTML = `<p>${note.name}</p>`;
      notesContainer.append(noteEl);
   }

   notesContainer.innerHTML = '';
   notes.map(render);

   return notes;
}

const replaceNotes = newNotes => (notes = newNotes);

button.addEventListener('click', handleEvent);
<button id="button">Click me!</button>
<section class="notes"></section>

1 Answers

Here is how to create a simple task list app without mutating anything except for the DOM.

const button = document.getElementById("button");
const section = document.getElementById("notes");
const template = document.getElementById("template");

template.parentNode.removeChild(template);

const render = notes => {
    button.onclick = event => {
        const name = prompt("How do you want to name a note?");
        render([...notes, { name }]);
    };

    while (section.lastChild) {
        section.removeChild(section.lastChild);
    }

    for (const note of notes) {
        const node = template.cloneNode(true);
        node.firstChild.firstChild.nodeValue = note.name;
        section.appendChild(node);
    }
};

render([]);
<button id="button">Click me!</button>
<section id="notes"></section>
<div id="template"><p>name</p></div>

For a detailed explanation, read my previous answer. https://stackoverflow.com/a/58642199/783743


You can use this pattern with localStorage too.

const button = document.getElementById("button");
const section = document.getElementById("notes");
const template = document.getElementById("template");

template.parentNode.removeChild(template);

const render = notes => {
    localStorage.setItem("notes", notes); // set notes

    button.onclick = event => {
        const name = prompt("How do you want to name a note?");
        render([...notes, { name }]);
    };

    while (section.lastChild) {
        section.removeChild(section.lastChild);
    }

    for (const note of notes) {
        const node = template.cloneNode(true);
        node.firstChild.firstChild.nodeValue = note.name;
        section.appendChild(node);
    }
};

render(localStorage.getItem("notes") || []); // get notes

Note that localStorage should only be used to save state that you want to use across sessions. It's not recommended to use localStorage as your application store. That would result in both bad performance and bad code structure.

Related