Skip to content
This repository has been archived by the owner on Jan 26, 2024. It is now read-only.

🚀 Feature: Update Vue Demo using Pinia and Composition API, with optional TypeScript and Script Setup syntax sugar #34

Open
2 tasks done
cindrmon opened this issue Mar 23, 2022 · 5 comments

Comments

@cindrmon
Copy link

🔖 Feature description

Basically, it is just an update to the current vue todo list demo to feature the new features for vite and vue 3, including, but not limited to, composition api, pinia, and script setup.

🎤 Pitch

Currently, it is seen that the demo project has already used vite under the hood, so why not use some of the new features it had already brought?

These new features include the new composition api, and the equally new <script setup> syntax sugar, which simplifies how we write our script tags in vue, eliminating a lot of boilerplate code and making it feel like a more natural javascript experience.

here's an example from the project's Login.vue component (still working on it though, this code is just for demonstration purposes.):

before

<script>
import { mapActions, mapGetters } from "vuex";
export default {
  name: "Login",
  data() {
    return {
      email: "",
      password: "",
    };
  },
  methods: {
    ...mapActions(["login"]),
    handleLogin(e) {
      e.preventDefault();
      console.log("Form submitted", this.email, this.password);
      this.login({
        email: this.email,
        password: this.password,
      });
    },
  }
};
</script>

after

<script setup>
  import { useAccountStore } from "../stores/account.js";
  import { refs } from "vue";
  
  const account = useAccountStore();

  const email: ref("");
  const password: ref("");

  const handleLogin = (e) => {
    e.preventDefault();
    console.log("Form Submitted", email.value, password.value);
    account.login({
      email: email.value,
      password: password.value
    })
  }
</script>

This also demonstrated how pinia also simplifies how you access the state just by writing two lines of code:

import { useAccountStore } from "../stores/account.js";
const account = useAccountStore();

you would have immediate access to that store just by doing that! any method or reactive value set in the account store can now be accessed just by typing account.. Its that simple!

Wow!

Another is the newer state management system, pinia. It also freshens up the experience in using a state management system, as it does not require modules and a main index.js file to handle multiple state managements. Modules can now be in their own file, called stores, and does not need to be imported into a single index.js file like what it used to be with vuex. Also, pinia can be imported easily through any components with ease.

your folder structure would be a noticeable difference when using pinia over vuex, look at the difference:

before

.
└ src
  └─ store
     ├─ modules
     │  ├─ account.js
     │  └─ todo.js
     └─ index.js
  

after

.
└ src
  └─ stores
     ├─ account.js
     └─ todo.js

**No need for an index.js file anymore inside the src/store folder!

You can even use the composition API in pinia, so that you can have that same boilerplate-less code for your state management system as well as your components!

here's an example comparison between the two. I used the account.js as a reference from the project (still working on it though, this code is just for demonstration purposes)

before

import api from "../../api";

const state = {
  account: null,
  session: null,
};

const actions = {
  signup: async ({ commit }, { email, password, name }) => {
    try {
      const account = await api.createAccount(email, password, name);
      await api.createSession(email, password);
      commit("setAccount", account);
    } catch (e) {
      console.log("Error creating Account");
      commit(
        "setError",
        {
          show: true,
          message: e.message,
          color: "red",
        },
        { root: true }
      );
    }
  },
  fetchAccount: async ({ commit }) => {
    try {
      const account = await api.getAccount();
      commit("setAccount", account);
    } catch (e) {
      console.log("Error getting Account");
    }
  },
  login: async ({ commit }, { email, password }) => {
    try {
      console.log(email, password);
      await api.createSession(email, password);
      const account = await api.getAccount();
      commit("setAccount", account);
    } catch (e) {
      console.log("Error creating Session", e);
      commit(
        "setError",
        {
          show: true,
          message: e.message,
          color: "red",
        },
        { root: true }
      );
    }
  },
  logout: async ({ commit }) => {
    try {
      await api.deleteCurrentSession();
      commit("setAccount", null);
    } catch (e) {
      console.log("Error deleting session");
      commit(
        "setError",
        {
          show: true,
          message: "Failed to logout",
          color: "red",
        },
        { root: true }
      );
    }
  },
};

const getters = {
  getAccount: (state) => state.account,
  getSession: (state) => state.session,
};

const mutations = {
  setAccount: (state, account) => (state.account = account),
};

export default {
  state,
  actions,
  getters,
  mutations,
};

after

import api from "../../api"
import {defineStore} from "pinia"
import {ref} from "vue"

export const useAccountStore = defineStore("account", () => {

    const account = ref()
    const session = ref()
    const error = ref()

    const signup = async (email, password, name) => {
        try {
            const account = await api.createAccount(email,password,name)
            account.value = await api.createSession(email,password)
        } catch (e) {
            console.error("Error creating account.")
            error.value = {
                {
                  show: true,
                  message: e.message,
                  color: "red",
                }
            }
        }
    }

    const fetchAccount = async () => {
        try {
            const account = await api.getAccount()
            account.value = account
        } catch (e) {
            console.error("Error getting Account")
        }
    }

    const login = async (email, password) => {
        try {
            console.log(email, password)
            await api.createSession(email, password)
            const account = await api.getAccount()
            account.value = account
        } catch (e) {
            console.error("Error creating Session:", e)
            error.value = {
                {
                  show: true,
                  message: e.message,
                  color: "red",
                }
            }
        }
    }

    const logout = async () => {
        try {
            await api.deleteCurrentSession()
            account.value = null
        } catch (e) {
            console.error("Error deleting Session")
            error.value =  {
                show: true,
                message: e.message,
                color: "red",
            }
        }
    }


    return {
        account,
        session,
        error,
        signup,
        fetchAccount,
        login,
        logout
    }

})

so as you can see, it used less boilerplate code, and you write your methods without actions or even mutations! as if you were writing composition api from a vue component.

besides all of that, this is just a suggestion. i'm currently trying out appwrite, and im currently trying out on how to incorporate what i have learned from the new composition api, pinia, and script setup, to see how all of these works together, and i would love to see it with the new features vue 3 and vite had brought to us.

im also curious on what other people think about updating or adding another demo project that uses pinia and composition api. and i hope you would also like to try appwrite with these new features!

👀 Have you spent some time to check if this issue has been raised before?

  • I checked and didn't find similar issue

🏢 Have you read the Code of Conduct?

@vic-cieslak
Copy link

can you open pull request or link to fork? I need to upgrade to composition api too, happy to double check your code.

@cindrmon
Copy link
Author

can you open pull request or link to fork? I need to upgrade to composition api too, happy to double check your code.

sure! i might be working on recreating this one after finals week, since im currently on crunch time with my schoolworks, but I'll definitely linke the code here once i've made it working properly

@titogarrido
Copy link

can you open pull request or link to fork? I need to upgrade to composition api too, happy to double check your code.

sure! i might be working on recreating this one after finals week, since im currently on crunch time with my schoolworks, but I'll definitely linke the code here once i've made it working properly

Looking forward for your fork :)

@rumbis
Copy link

rumbis commented Sep 28, 2022

Count me in please for the boilerplate :)

@markosole
Copy link

That would be fantastic, I am in :) As @rumbis said it's great for boilerplate. It's hard to find nice clean "how should be done" simple project to learn from.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants