Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can I use functional api with vuex? #18

Closed
mspoulsen opened this issue Jul 2, 2019 · 11 comments
Closed

Can I use functional api with vuex? #18

mspoulsen opened this issue Jul 2, 2019 · 11 comments

Comments

@mspoulsen
Copy link

Hi,

I am really eager to try this new api and especially the typescript integration. But can I use this api with vuex? If so could anybody provide an example? 馃檪

Thanks!

@a9
Copy link

a9 commented Jul 2, 2019

see comment #8 (comment)

@SilentDepth
Copy link

Actually, after splitting states into hooks, I removed vuex from my project dependencies. 馃お

@u3u
Copy link

u3u commented Jul 8, 2019

Hi, everyone, I created a vue-hooks repository and package.
It contains commonly used hooks (e.g: vuex / vue-router).
Documentation has not been written yet, welcome everyone to contribute! 馃槃

@gianko
Copy link

gianko commented Jul 18, 2019

@SilentDepth how are you sharing sharing vue-function-api state between components?

care to share an example? please

@SilentDepth
Copy link

@gianko Just like this:

/* hook-msg.js */

import {value as binding} from 'vue-function-api'

const msg = binding('hello world')

export default function useMsg () {
  return {
    msg,
  }
}
/* comp-a.vue */

import useMsg from './hook-msg'

export default {
  setup () {
    const {msg} = useMsg()

    return {
      msg,
    }
  },
}
/* comp-b.vue */

import {computed} from 'vue-function-api'
import useMsg from './hook-msg'

export default {
  setup () {
    const {msg} = useMsg()

    return {
      msgUpperCased: computed(() => msg.value.toUpperCase()),
    }
  },
}

@gianko
Copy link

gianko commented Jul 18, 2019

Thanks!... I was getting an error about using vue function api before calling the use plugin.

@thommath
Copy link

I used the trick in the #8 answer but built on it a bit by making a small vuex plugin to do the wrapping of my getters.

Feels kind of hacky, but then all getters can be unpacked in one line

/* store-plugin.js */
import { computed } from 'vue-function-api'

let getters = {};

const myPlugin = store => {
  Object.keys(store.getters)
    .forEach(key => (getters[key] = computed(() => store.getters[key])));
}

export {
  myPlugin,
  getters
};

Then the computed getters can be accessed with:

/* some-vue-file.vue */
import { getters } from './store-plugin.vue';

const { someGetter, someOtherGetter } = getters;

@furryablack
Copy link

furryablack commented Jul 27, 2019

What do you think about https://github.com/zerobias/effector as a state manager?

Vue-function-api is the great thing with jsx =)
I thinking vuex doesn't need anymore =D

See:

// @app/core/hooks/use-value
import { value } from "vue-function-api"

export const useValue = (initialValue, lazy) => {
  lazy = !!lazy
  const state = value(initialValue)
  const dispatch = (newValue) => {
    if (!lazy) {
      state.value = newValue
    } else if (state.value !== newValue) {
      state.value = newValue
    }
  }
  const reset = () => dispatch(initialValue)
  return [state, dispatch, reset]
}

// @app/core/hooks/use-reducer
import { useValue } from "./use-value"

export const useReducer = (reducer, initialValue, lazy) => {
  const [state, set, reset] = useValue(initialValue, lazy)
  const dispatch = (payload) => {
    const reducerResult = reducer(state.value, payload)
    set(reducerResult)
  }
  return [state, dispatch, reset]
}

Example:

import { useReducer } from "@app/core/hooks/use-reducer"


function reducer(value, payload) {
    switch (payload.type) {
      case "increment":
        return value + 1
      case "decrement":
        return value - 1
      default:
        throw new Error()
    }
}

export const ExampleCounter = {
  setup() {
    const initialValue = 0

    const [count, updateCount, reset] = useReducer(reducer, initialValue)

    const increment = () => updateCount({ type: "increment" })
    const decrement = () => updateCount({ type: "decrement" })

    // No needs, we have reset state function already
    // const reset = () => updateCount({ type: "reset" })

    return {
      count,
      increment,
      decrement,
      reset,
    }
  },

  render(h) {
    return (
      <div>
        Count: {this.counter.toString()}
        <button vOn:click_prevent={this.increment}>+</button>
        <button vOn:click_prevent={this.decrement}>-</button>
        <button vOn:click_prevent={this.reset}>reset</button>
      </div>
    )
  },
}

PS:
Example uses jsx - vue requires the next babel plugins for that

{
  plugins: [
    "@vue/babel-plugin-transform-vue-jsx",
    "@vue/babel-sugar-v-on",
  ]
}

@posva
Copy link
Member

posva commented Jul 31, 2019

Duplicate of #8

@posva posva closed this as completed Jul 31, 2019
@blowsie
Copy link

blowsie commented Dec 5, 2019

@SilentDepth i presume this example is not still relevant?
I tried to do the equivalent using ref and got an error Uncaught Error: [vue-composition-api] must call Vue.use(plugin) before using any function.

@gianko Just like this:

/* hook-msg.js */

import {value as binding} from 'vue-function-api'

const msg = binding('hello world')

export default function useMsg () {
  return {
    msg,
  }
}
/* comp-a.vue */

import useMsg from './hook-msg'

export default {
  setup () {
    const {msg} = useMsg()

    return {
      msg,
    }
  },
}
/* comp-b.vue */

import {computed} from 'vue-function-api'
import useMsg from './hook-msg'

export default {
  setup () {
    const {msg} = useMsg()

    return {
      msgUpperCased: computed(() => msg.value.toUpperCase()),
    }
  },
}

@SilentDepth
Copy link

@blowsie You need to call Vue.use() first, before any composition api being used.

The missing entry file of my example:

/* main.js */

import Vue from 'vue'
import './use-composition-api'
import App from './app.vue'

new Vue({
  render: h => h(App),
})
/* use-composition-api.js */

import Vue from 'vue'
import CompositionApi from '@vue/composition-api'

Vue.use(CompositionApi)

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

No branches or pull requests

9 participants