A Vue composition that let you compose a ref with a function from values to refs

vue-use-switch-map

npm i -S vue-use-switch-map

A Vue 3 composition package that exports:

  • useSwitchMap, a function to compose a ref with a function from values to refs
  • useSwitchMapO, a function to compose a ref with a function from values to objects containing refs

This package is designed for binding refs to Vue composition functions, which, in turn, may produce one or more refs.

It works with both Vue 3 and Vue 2 + @vue/composition-api because I’m using vue-demi, and it is written in TypeScript.

The behaviour is similar to the RxJS switchMap operator.
The composition itself will produce a ref, called switchMappedRef. Each time the composed ref changes:

  1. the ref previously returned by the composed function will be discarded, so the switchMappedRef will no longer be updated by its changes
  2. the composed function runs again, producing a new ref
  3. switchMappedRef is connected to this fresh ref, receiving its updates

Menu:

useSwitchMap

function useSwitchMap<T, U>(
    ref: Ref<T>,
    projectionFromValuesToRefs: (value: T, scf: SetCleanupFunction) => Ref<U>
): Ref<U>

useSwitchMap takes a ref and a function from values to refs, returning a ref that will see its value changed because of two main reasons: the composed function changes its returned ref’s value, or the input ref’s value has been changed.
The first case is not special at all, I’m sure you already use some Vue 3 composition functions that internally listen to some events, or use some timeouts, promises, etc. and therefore change the ref’s value they return in response to those happenings.
The second case is more tricky, because a lot of stuff happens when the input ref’s value is changed. The composed function is re-runned from scratch, producing a new ref R. This ref is automagically substituted to the one that useSwitchMap has returned, in such a way that it will receive only the updates from the last ref R produced.

A function is passed to projectionFromValuesToRefs to let it set a cleanup function that will be called just before projectionFromValuesToRefs is runned again.

example: mouse tracker

We want to track all the pointer positions after an initial click that starts the tracking. We want to be able to restart the tracking from scratch at each click.

Here it is:

import { useSwitchMap } from 'vue-use-switch-map'
import { ref } from 'vue'

// click handling
const mouseClickPoisitonRef = ref({ x: -1, y: -1 })

function updateMouseCLickPositionRef(x, y) {
    mouseClickPoisitonRef.value.x = x
    mouseClickPoisitonRef.value.y = y
}

const clickListener = (clickEvent) => {
    updateMouseCLickPositionRef(clickEvent.screenX, clickEvent.screenY)
}

// each time we click, mouseClickPoisitonRef is updated
window.addEventListener('click', clickListener)

// positions tracking
const switchMappedRef = useSwitchMap(mouseClickPoisitonRef, (initP, cleanup) => {
    // do nothing until we click
    if (initP.x === -1) return ref([])

    const psRef = ref([{ x: initP.x, y: initP.y }])

    const moveListener = (moveEvent) => {
        psRef.value.push({
            x: moveEvent.screenX,
            y: moveEvent.screenY,
        })
    }

    // add the new position inside the positions array ref
    window.addEventListener('mousemove', moveListener)

    cleanup(() => window.removeEventListener('mousemove', moveListener))

    return psRef
})

Here switchMappedRef will be a ref to an array that will be updated with the pointer positions after the first click. Each time we click somewhere on the screen, the function that tracks the mouse will be called again, so switchMappedRef will be updated with a new, fresh array. We do use the cleanup function to set a function that will remove the event listener because, even if older listeners do not interfere with switchMappedRef, we don’t like memory leaks.

useSwitchMapO

A function like useSwitchMap is not enough in the case the composed function returns an object where each property is itself a ref. This is why useSwitchMapO was born.

function useSwitchMapO<T, R extends object>(
    ref: Ref<T>,
    projectionFromValuesToRefs: (value: T, scf: SetCleanupFunction) => R
): R

example: fetch

Our goal is to compose the following useFetch Vue composition function with a ref, so that each time the ref is changed the function will refetch the data. This useFetch function will return an object containing three refs: one that signal if the fetch is in a pending state, one for the resulting data and the last for a possible error message.

Using useSwitchMapO will be a breeze:

import { useSwitchMapO } from 'vue-use-switch-map'
import { ref, computed } from 'vue'

const useFetch = (url) => {
    const dataRef = ref(null)
    const errorMessageRef = ref('')
    const isPendingRef = ref(true)

    fetch(url)
        .then((response) => response.json())
        .then((data) => (dataRef.value = data))
        .catch((error) => (errorMessageRef.value = error.message))
        .finally(() => (isPendingRef.value = false))

    return { dataRef, errorMessageRef, isPendingRef }
}

// for example, counterRef could be a prop
const counterRef = ref(0)

function incrementCounterRef() {
    counterRef.value++
}

const urlRef = computed(() => `https://jsonplaceholder.typicode.com/todos/${counterRef.value}`)

// here it is
const { dataRef, errorMessageRef, isPendingRef } = useSwitchMapO(urlRef, useFetch)

As you can see, we don’t have to worry about older fetch calls that may take longer than the last one, with the risk of having our dataRef, errorMessageRef and isPendingRef changed by them.

Moreover, you can always use the cleanup function argument to set up a cleaup function, e.g. to stop an asynchronous computation:

const useFetch = (url, cleanup) => {
    const dataRef = ref(null)
    const errorMessageRef = ref('')
    const isPendingRef = ref(true)

    const controller = new AbortController()
    const signal = controller.signal

    fetch(url, { signal })
        .then((response) => response.json())
        .then((data) => (dataRef.value = data))
        .catch((error) => (errorMessageRef.value = error.message))
        .finally(() => (isPendingRef.value = false))

    cleanup(() => controller.abort())

    return { dataRef, errorMessageRef, isPendingRef }
}

In this case, though, the promise will rejects with an AbortError, so the magic of useSwitchMapO is still needed to prevent the problems we have just discussed.

Common needs

The Vue composition function depends on some static configuration

Let’s say we have a Vue composition function like the following:

function useSomething(value, config [, cleanup]) {
    // ...
    return useSomethingRef
}

We want to bind such a function to aRef using useSwitchMap. How do we do that?

const makeUseSomething = (config) => (value [, cleanup]) => useSomething(value, config [, cleanup])

const switchMappedRef = useSwitchMap(aRef, makeUseSomething(config))

The composition involves more than one ref

Let’s say we need to bind more than one ref to a composition function:

function useSomething(value, anotherValue [, cleanup]) {
    // ...
    return useSomethingRef
}

const switchMappedRef = useSwitchMap(aRef, anotherRef, useSomething)
// that's not how 'useSwitchMap' works

How do we do that? Simple, we have to create an object ref:

const objectRef = computed(() => ({ value: aRef.value, anotherValue: anotherRef.value }))

const switchMappedRef = useSwitchMap(
    objectRef,
    (object [, cleanup]) => useSomething(object.value, object.anotherValue [, cleanup])
)

Contribute

I’ve tried my best to test it, but I clearly suck at it. I’ve messed a lot with jest, fake timers and watchers without much success, therefore I was unable to express some advanced use cases that I had to personally test using home made solutions. Therefore, any contribution in this direction is really really appreciated 😊.

Notes

You can read more about this package in this blog post.

Download Details:

Author: jfet97

Source Code: https://github.com/jfet97/vue-use-switch-map

#vue #vuejs #javascript

What is GEEK

Buddha Community

A Vue composition that let you compose a ref with a function from values to refs
Luna  Mosciski

Luna Mosciski

1600583123

8 Popular Websites That Use The Vue.JS Framework

In this article, we are going to list out the most popular websites using Vue JS as their frontend framework.

Vue JS is one of those elite progressive JavaScript frameworks that has huge demand in the web development industry. Many popular websites are developed using Vue in their frontend development because of its imperative features.

This framework was created by Evan You and still it is maintained by his private team members. Vue is of course an open-source framework which is based on MVVM concept (Model-view view-Model) and used extensively in building sublime user-interfaces and also considered a prime choice for developing single-page heavy applications.

Released in February 2014, Vue JS has gained 64,828 stars on Github, making it very popular in recent times.

Evan used Angular JS on many operations while working for Google and integrated many features in Vue to cover the flaws of Angular.

“I figured, what if I could just extract the part that I really liked about Angular and build something really lightweight." - Evan You

#vuejs #vue #vue-with-laravel #vue-top-story #vue-3 #build-vue-frontend #vue-in-laravel #vue.js

A Vue composition that let you compose a ref with a function from values to refs

vue-use-switch-map

npm i -S vue-use-switch-map

A Vue 3 composition package that exports:

  • useSwitchMap, a function to compose a ref with a function from values to refs
  • useSwitchMapO, a function to compose a ref with a function from values to objects containing refs

This package is designed for binding refs to Vue composition functions, which, in turn, may produce one or more refs.

It works with both Vue 3 and Vue 2 + @vue/composition-api because I’m using vue-demi, and it is written in TypeScript.

The behaviour is similar to the RxJS switchMap operator.
The composition itself will produce a ref, called switchMappedRef. Each time the composed ref changes:

  1. the ref previously returned by the composed function will be discarded, so the switchMappedRef will no longer be updated by its changes
  2. the composed function runs again, producing a new ref
  3. switchMappedRef is connected to this fresh ref, receiving its updates

Menu:

useSwitchMap

function useSwitchMap<T, U>(
    ref: Ref<T>,
    projectionFromValuesToRefs: (value: T, scf: SetCleanupFunction) => Ref<U>
): Ref<U>

useSwitchMap takes a ref and a function from values to refs, returning a ref that will see its value changed because of two main reasons: the composed function changes its returned ref’s value, or the input ref’s value has been changed.
The first case is not special at all, I’m sure you already use some Vue 3 composition functions that internally listen to some events, or use some timeouts, promises, etc. and therefore change the ref’s value they return in response to those happenings.
The second case is more tricky, because a lot of stuff happens when the input ref’s value is changed. The composed function is re-runned from scratch, producing a new ref R. This ref is automagically substituted to the one that useSwitchMap has returned, in such a way that it will receive only the updates from the last ref R produced.

A function is passed to projectionFromValuesToRefs to let it set a cleanup function that will be called just before projectionFromValuesToRefs is runned again.

example: mouse tracker

We want to track all the pointer positions after an initial click that starts the tracking. We want to be able to restart the tracking from scratch at each click.

Here it is:

import { useSwitchMap } from 'vue-use-switch-map'
import { ref } from 'vue'

// click handling
const mouseClickPoisitonRef = ref({ x: -1, y: -1 })

function updateMouseCLickPositionRef(x, y) {
    mouseClickPoisitonRef.value.x = x
    mouseClickPoisitonRef.value.y = y
}

const clickListener = (clickEvent) => {
    updateMouseCLickPositionRef(clickEvent.screenX, clickEvent.screenY)
}

// each time we click, mouseClickPoisitonRef is updated
window.addEventListener('click', clickListener)

// positions tracking
const switchMappedRef = useSwitchMap(mouseClickPoisitonRef, (initP, cleanup) => {
    // do nothing until we click
    if (initP.x === -1) return ref([])

    const psRef = ref([{ x: initP.x, y: initP.y }])

    const moveListener = (moveEvent) => {
        psRef.value.push({
            x: moveEvent.screenX,
            y: moveEvent.screenY,
        })
    }

    // add the new position inside the positions array ref
    window.addEventListener('mousemove', moveListener)

    cleanup(() => window.removeEventListener('mousemove', moveListener))

    return psRef
})

Here switchMappedRef will be a ref to an array that will be updated with the pointer positions after the first click. Each time we click somewhere on the screen, the function that tracks the mouse will be called again, so switchMappedRef will be updated with a new, fresh array. We do use the cleanup function to set a function that will remove the event listener because, even if older listeners do not interfere with switchMappedRef, we don’t like memory leaks.

useSwitchMapO

A function like useSwitchMap is not enough in the case the composed function returns an object where each property is itself a ref. This is why useSwitchMapO was born.

function useSwitchMapO<T, R extends object>(
    ref: Ref<T>,
    projectionFromValuesToRefs: (value: T, scf: SetCleanupFunction) => R
): R

example: fetch

Our goal is to compose the following useFetch Vue composition function with a ref, so that each time the ref is changed the function will refetch the data. This useFetch function will return an object containing three refs: one that signal if the fetch is in a pending state, one for the resulting data and the last for a possible error message.

Using useSwitchMapO will be a breeze:

import { useSwitchMapO } from 'vue-use-switch-map'
import { ref, computed } from 'vue'

const useFetch = (url) => {
    const dataRef = ref(null)
    const errorMessageRef = ref('')
    const isPendingRef = ref(true)

    fetch(url)
        .then((response) => response.json())
        .then((data) => (dataRef.value = data))
        .catch((error) => (errorMessageRef.value = error.message))
        .finally(() => (isPendingRef.value = false))

    return { dataRef, errorMessageRef, isPendingRef }
}

// for example, counterRef could be a prop
const counterRef = ref(0)

function incrementCounterRef() {
    counterRef.value++
}

const urlRef = computed(() => `https://jsonplaceholder.typicode.com/todos/${counterRef.value}`)

// here it is
const { dataRef, errorMessageRef, isPendingRef } = useSwitchMapO(urlRef, useFetch)

As you can see, we don’t have to worry about older fetch calls that may take longer than the last one, with the risk of having our dataRef, errorMessageRef and isPendingRef changed by them.

Moreover, you can always use the cleanup function argument to set up a cleaup function, e.g. to stop an asynchronous computation:

const useFetch = (url, cleanup) => {
    const dataRef = ref(null)
    const errorMessageRef = ref('')
    const isPendingRef = ref(true)

    const controller = new AbortController()
    const signal = controller.signal

    fetch(url, { signal })
        .then((response) => response.json())
        .then((data) => (dataRef.value = data))
        .catch((error) => (errorMessageRef.value = error.message))
        .finally(() => (isPendingRef.value = false))

    cleanup(() => controller.abort())

    return { dataRef, errorMessageRef, isPendingRef }
}

In this case, though, the promise will rejects with an AbortError, so the magic of useSwitchMapO is still needed to prevent the problems we have just discussed.

Common needs

The Vue composition function depends on some static configuration

Let’s say we have a Vue composition function like the following:

function useSomething(value, config [, cleanup]) {
    // ...
    return useSomethingRef
}

We want to bind such a function to aRef using useSwitchMap. How do we do that?

const makeUseSomething = (config) => (value [, cleanup]) => useSomething(value, config [, cleanup])

const switchMappedRef = useSwitchMap(aRef, makeUseSomething(config))

The composition involves more than one ref

Let’s say we need to bind more than one ref to a composition function:

function useSomething(value, anotherValue [, cleanup]) {
    // ...
    return useSomethingRef
}

const switchMappedRef = useSwitchMap(aRef, anotherRef, useSomething)
// that's not how 'useSwitchMap' works

How do we do that? Simple, we have to create an object ref:

const objectRef = computed(() => ({ value: aRef.value, anotherValue: anotherRef.value }))

const switchMappedRef = useSwitchMap(
    objectRef,
    (object [, cleanup]) => useSomething(object.value, object.anotherValue [, cleanup])
)

Contribute

I’ve tried my best to test it, but I clearly suck at it. I’ve messed a lot with jest, fake timers and watchers without much success, therefore I was unable to express some advanced use cases that I had to personally test using home made solutions. Therefore, any contribution in this direction is really really appreciated 😊.

Notes

You can read more about this package in this blog post.

Download Details:

Author: jfet97

Source Code: https://github.com/jfet97/vue-use-switch-map

#vue #vuejs #javascript

Vincent Lab

Vincent Lab

1605017502

The Difference Between Regular Functions and Arrow Functions in JavaScript

Other then the syntactical differences. The main difference is the way the this keyword behaves? In an arrow function, the this keyword remains the same throughout the life-cycle of the function and is always bound to the value of this in the closest non-arrow parent function. Arrow functions can never be constructor functions so they can never be invoked with the new keyword. And they can never have duplicate named parameters like a regular function not using strict mode.

Here are a few code examples to show you some of the differences
this.name = "Bob";

const person = {
name: “Jon”,

<span style="color: #008000">// Regular function</span>
func1: <span style="color: #0000ff">function</span> () {
    console.log(<span style="color: #0000ff">this</span>);
},

<span style="color: #008000">// Arrow function</span>
func2: () =&gt; {
    console.log(<span style="color: #0000ff">this</span>);
}

}

person.func1(); // Call the Regular function
// Output: {name:“Jon”, func1:[Function: func1], func2:[Function: func2]}

person.func2(); // Call the Arrow function
// Output: {name:“Bob”}

The new keyword with an arrow function
const person = (name) => console.log("Your name is " + name);
const bob = new person("Bob");
// Uncaught TypeError: person is not a constructor

If you want to see a visual presentation on the differences, then you can see the video below:

#arrow functions #javascript #regular functions #arrow functions vs normal functions #difference between functions and arrow functions

Abigale  Yundt

Abigale Yundt

1599661800

Forms of Composition in JavaScript and React

One of the core ideas in functional programming is composition: building larger things from smaller things. The canonical example of this idea should be familiar with legos.

Multiple legos can be joined and yield another lego that can continue to be built on and attached to others. In functional programming, the basic unit for composition is functions and larger functions are built by connecting and combining smaller ones.

When asked how to handle a particular scenario, edge case, or requirement, a functional programmer will nearly always answer: ‘with a function’.

Object-oriented concepts like factories, strategy mangers, or polymorphism don’t have an equivalent in the functional paradigm. Functional programming has its own key concepts, composition is one.

A (quick) Aside

One distinction between functional and object oriented programming is best seen in the difference between

circle.area()andarea(circle). In the first version - a more object oriented style -areais a method that exists on theCircleclass and can only be called onCircleinstances. In the second,areais a function that accepts an object. Unlike the object oriented version, it can act on any object that conforms to the type expected byarea.

This illustrates a core difference between the two paradigms. In an object oriented world, data and functionality are coupled -

areais a function on instances ofCircleobjects limited to objects created by that class. In functional programming, data and functionality are decoupled -areais a function that can act on any object that has the required properties.

While object oriented patterns have interfaces, inheritance and other mechanisms for sharing behavior like calculating the area of various shapes, it can often feel like you’re standing in an abandoned abstract factory churning out reverse proxies* 🙃

*I’ve never written an abstract factory and this is just a cheeky line to maintain engagement. Like all things, OO is another tool to leverage when needed.

Forms of Composition

Functions are not the sole unit of composition and the principle extends beyond the domain of functional programming. ReactJS uses components as a unit of composition. Hooks too like

useStateare another unit. If you’re really focusing, you may notice that hooks are just regular functions which is why they are great for composition.

Its possible to build larger components from smaller components, and write custom hooks that extend the capability of existing hooks.

Composition relies on recursion to build larger abstractions from smaller abstractions but with each abstraction layer as the same type as all the others. Once a compositional unit like functions or components exist, you immediately get a compositional model that allows for building high level abstractions very quickly for free. Each layer of abstraction is fundamentally the same type of thing as all the other layers.

An Example of (Functional) Composition

Let’s begin with three functions.

const toUpperCase = str => str.toUpperCase();
const appendExclamationPoints = str => str + '!';
const split = str => str.split('');

Often code takes the output of one function and uses it as the input to another. This is the idea of a pipeline. Data in, data out.

split(appendExclamationPoints(toUpperCase('hello world'))) 
// ["HELLO", "WORLD!"]

While the above works, it isn’t the easiest to read. A simpler abstraction is a single function that can be invoked with some string passed as the parameter.

function appendExclamationPointAndSplitOnSpace(someString) {
    return (someString.toUpperCase() + '!').split();
}

appendExclamationPointAndSplitOnSpaceagic('hello world') 
// ["Hello", "World!"]

The above function, while meeting the requirements perfectly, isn’t necessarily clean code. It uses an imperative style, specifying each operation to perform to get the desired result. While it may be simple enough to read and understand, a more declarative style would be even easier.

Functional programming can help simplify the above through a helper function called

compose. Compose accepts an arbitrary number of functions, and returns a new function that runs each of the functions passed in such that the output of the previous functions is used as the input to the next

t appendExclamationPointAndSplitOnSpace = compose(
    split, 
    appendExclamationPoints, 
    toUpperCase
);

appendExclamationPointAndSplitOnSpace('hello world') 
// ["Hello", "World!"]

Note that the functions execute in a right to left wrapping manner similar to the original example. That is,

splitinvokes the result ofappendExclamationPointswhich invokes the result oftoUpperCase. This results in a declarative style, with no direct function calls or references to the data and methods that exist on the data type. A new function is created that accepts the data and computes the result. Most importantly, we’re able to build the new function from existing smaller functions that we already have or are trivial to write.

Composing functions requires adherence to the following intuitive rule. The output type of function A must match the input type of function B given that B runs with the output from function A. In a practical example, if a function that returns a number is composed with a function that expects a string, some unexpected errors might creep in.

Various implementations of

composecan be found in Lodash, Redux, and other JavaScript libraries. Its certainly not magical, and can be written in under 10 lines.

#functional-programming #javascript #reactjs #composition #pure-functions #compositions-in-javascript #compositions-in-react #javascript-top-story

Vue 3 Tutorial (for Vue 2 Users)

Vue 3 has not been officially released yet, but the maintainers have released beta versions for us punters to try and provide feedback on.

If you’re wondering what the key features and main changes of Vue 3 are, I’ll highlight them in this article by walking you through the creation of a simple app using Vue 3 beta 9.

I’m going to cover as much new stuff as I can including fragments, teleport, the Composition API, and several more obscure changes. I’ll do my best to explain the rationale for the feature or change as well.


What we’ll build

We’re going to build a simple app with a modal window feature. I chose this because it conveniently allows me to showcase a number of Vue 3 changes.

Here’s what the app looks like in it’s opened and closed states so you can picture in your mind what we’re working on:

Vue 3 app modal

Vue 3 installation and setup

Rather than installing Vue 3 directly, let’s clone the project vue-next-webpack-preview which will give us a minimal Webpack setup including Vue 3.

$ git clone https://github.com/vuejs/vue-next-webpack-preview.git vue3-experiment
$ cd vue3-experiment
$ npm i

Once that’s cloned and the NPM modules are installed, all we need to do is remove the boilerplate files and create a fresh main.js file so we can create our Vue 3 app from scratch.

$ rm -rf src/*
$ touch src/main.js

Now we’ll run the dev server:

$ npm run dev

Creating a new Vue 3 app

Straight off the bat, the way we bootstrap a new Vue app has changed. Rather than using new Vue(), we now need to import the new createApp method.

We then call this method, passing our Vue instance definition object, and assign the return object to a variable app.

Next, we’ll call the mount method on app and pass a CSS selector indicating our mount element, just like we did with the $mount instance method in Vue 2.

src/main.js

import { createApp } from "vue";

const app = createApp({
  // root instance definition
});

app.mount("#app");

Reason for change

With the old API, any global configuration we added (plugins, mixins, prototype properties etc) would permanently mutate global state. For example:

src/main.js

// Affects both instances
Vue.mixin({ ... })

const app1 = new Vue({ el: '#app-1' })
const app2 = new Vue({ el: '#app-2' })

This really shows up as an issue in unit testing, as it makes it tricky to ensure that each test is isolated from the last.

Under the new API, calling createApp returns a fresh app instance that will not be polluted by any global configuration applied to other instances.

Learn more: Global API change RFC.

#vue.js #components #composition api #design patterns #vue 3 #vue