skip to Main Content

I’m new to AlpineJS. I have some production knowledge of React and some basics of Vue. But one of the things I’m not getting about AlpineJS and I did not find a direct answer to this from any of the documentation or tutorial videos on AlpineJS, that’s why I’m asking this. It’s obviously my lack of knowledge, but I’m afraid, that’s true for every newcomer. 🙂

Suppose, I have the following code (summarized):

<div x-data="{ array1 = [], array2 = [], total = 0 }">
    <!-- ✅ Success: Get user input and populate array1 here -->
    <!-- ✅ Success: Get user input and populate array2 here too -->
    <button x-show="$store.total === 0; console.log("👉 ", $store.total)">
        Do Something
    </button>
</div>

<script>
    const myFunc = (array1, array2, total) => {
        // Reference: https://stackoverflow.com/q/76607996/1743124
        const hash = array2.reduce((h, s) => {
            h[s] = (h[s] || 0) + 1;
            return h;
        }, {});

        array1.map(function(s) {
            if(hash[s] && hash[s]--) {
                console.log("🏌️‍♂️ total ", total);
                Alpine.store('total', total--); // 🟥 QUESTION IS HERE.
                console.log("🕴️ total-- ", total);
                return '✅' + s;
            } else {
                return s;
            }
        });
    }
</script>

The myFunc code is taken from this SO thread.

As you can see that I achieved some of the things. My question is about How can I update the total state from inside the function myFunc and that can be available outside the function for general use?

As in React, we can easily update a state like the below:

// REACT JS EXAMPLE FOR A CONTRAST.

const [total, setTotal] = useState(0);

// Somewhere setTotal(500);

const myFunc = () => {
    setTotal(total--); // under certain condition within a 🔄️ loop
    return true;
};

Here, though the function is returning some other thing, the state is been updated using a setState directive, but we can get the updated value of total anywhere outside.

How can I do a similar thing in AlpineJS? I understood that it can be done using the Store global, but it’s not working as expected. The console.logs inside the function were showing exactly what I expected, a 0 (zero) when it should be. But the console.log($store.total) is giving me 1 ⚠️:

All the console.logs

What am I doing wrong here?
Is this a desired effect of the Store global in AlpineJS?

PS. The event that I’m working with is @keyup when all the things are getting fired.

2

Answers


  1. Although I don’t understand what total represents and how you get it before passing it to myFunc I can see that you are mixing x-data with store and also initializing store inside a loop. Issue is probably caused by these things.

    You can move it all in store (data and functions). And then show the data in HTML and call functions on events. Something like components in Vue.js where you have data and methods and then use it in <template>.

    I would do it something like this:

    document.addEventListener("alpine:init", () => {
      Alpine.store('myStore', {
        input1: '',
        input2: '',
        total: 0,
        result: '',
    
        myFunc() {
          const array1 = this.input1 ? this.input1.split(',') : []
          const array2 = this.input2 ? this.input2.split(',') : []
    
          const hash = array2.reduce((h, s) => {
            h[s] = (h[s] || 0) + 1;
            return h;
          }, {})
    
          this.result = array1.map(s => hash[s] && hash[s]-- ? '✅' + s : s)
          
          array1.map(s => {
            if (hash[s] && hash[s]--) {
              console.log("🏌️‍♂️ total ", this.total)
              this.total-- // 🟥 QUESTION IS HERE.
              console.log("🕴️ total-- ", this.total)
              return '✅' + s;
            } else {
              return s
            }
          })
        }
      })
    })
    

    total will go to negative here when conditions are met but you can easily pass param to myFunc with whatever data you need and work with it.

    Full example is here https://jsfiddle.net/z2w0p7m3/

    Login or Signup to reply.
  2. From all I gather, you’re simply confused as to why total is 1 within your $store, even though it logs "0" one line later. That’s simple JS operator logic, which applies to multiple coding languages.

    Let me explain: You have a "post-" and "pre-decrement" operator (also for increment). It’s basically whether the operator is before (pre) or after (post) the variable, and the difference is the order of operations. In the pre operation, the operator is first executed, and then the variable is evaluated. In the post operator, the variable is first evaluated, and then the operator is executed.

    Example:

    let x = 3;
    let y = x--;
    // x = 2, y = 3;
    
    let x = 3;
    let y = --x;
    // x = 2, y = 2;
    

    Basically what is happening, is that you’re storing the value of total, and then you’re decrementing it. If you’re expecting the stored value to be 0, you should use pre-decrement (--total).

    You can read more details about it here.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search