Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
Andrew Smith
@silentworks
I just notice that passing defaultParamaters to the svelteRenderer can also capture the login event at a global level
Josh Duff
@TehShrike
Do you really want every state to be able to call that method, though?
Andrew Smith
@silentworks
:-)
Not at all, but its just a finding I wasn't aware of
for instance, that would make a good candidate for logout
But hoisting would kill it
So i guess not
Josh Duff
@TehShrike
yeah, for the renderers I've found that it can be handy to allow the coder to hook in frameworky global bits
For logging out, I prefer having a "logout" state that talks to the server in its resolve
So you make the logout happen with state.go('logout') or having the user click on a link <a href="{{ asr.makePath('logout') }}">logout</a>
Andrew Smith
@silentworks
boom
thanks
Josh Duff
@TehShrike
once you get used to driving important changes through the URL, it's glorious
the user never has to worry about reloading the page and ending up in an awkward state
and your views can become closer and closer to pure functions of the url
GavinRay97
@GavinRay97
@TehShrike If you're around, I wanted to ask you for some quick info
Josh Duff
@TehShrike
wazzaaaaaap
GavinRay97
@GavinRay97

I posted this in the MobX gitter earlier:

I have a question which may seem sort of stupid.

I am a massive fan of MobX with injected store decorators and observer/observable pattern, it makes sense and deprecates the need the for "state" if you will in components since they're essentially "hot-wired" to the store (global app state).
I've been using state management libraries since Flux was introduced, before Redux ever existed.
I'm curious if there's a way to make an agnostic implementation of MobX that you can configure to work with Vue/React/Angular/Aurelia, etc.

Every time I've used MobX, I've needed (or appeared to need) a "binding" package for that UI framework.
Would it not be possible to write an agnostic implementation that you could pass framework elements or functions into for context?

Response: "I bet you there is. Just like how TehShrike made an agnostic version of ui-router. https://gitter.im/TehShrike/abstract-state-router"
I'm wondering whether or not what I'm trying to do is feasible with AST or any other package.
Josh Duff
@TehShrike
The way that ASR integrates with every other library is by way of a custom adapter/renderer for each library: https://github.com/TehShrike/abstract-state-router#current-renderer-implementations
If you use ASR, it's relatively easy to hook up your state solution of choice to every component that gets mounted automatically by ASR when the route changes
GavinRay97
@GavinRay97
So say with Vue, for example, the main.js typically looks something like this:
import Vue from 'vue';
import App from './App';

new Vue({
  el: '#app',
  template: '<App/>',
  components: { App },
  data: { someGlobalStorePackageOrObject }
});
Josh Duff
@TehShrike
Handling any state library could be tricky, you'd have to define a common language that would let the components communicate out
GavinRay97
@GavinRay97
import createStateRouter from 'abstract-state-router';
import Vue from 'vue';
import App from './App';

const VueInstance = new Vue({
  el: '#app',
  template: '<App/>',
  components: { App },
  data: { someGlobalStorePackageOrObject }
});
const stateRouter = createStateRouter(makeRenderer, VueInstance)
?
TehShrike/abstract-state-router#114
Josh Duff
@TehShrike
I don't think that pull request is going to go anywhere :-x
GavinRay97
@GavinRay97
I saw this PR, curious if "Root element can be a function" means I can pass In an instance of a Vue object.
Oh, lmao :joy:
I have written this:
The interesting bit is the /src/store folder
Josh Duff
@TehShrike
import createStateRouter from 'abstract-state-router'
import makeVueStateRenderer from 'vue-state-renderer'
import hookUpStoreToAllRenderedStates from 'library-that-you-could-make'
import reduxOrWhateverAdapter from 'adapter-library-for-library-that-you-could-make'

import App from './App'


const renderer = hookUpStoreToAllRenderedStates(makeVueStateRenderer(), reduxOrWhateverAdapter())
const stateRouter = createStateRouter(renderer)

stateRouter.add({
    name: 'app',
    route: 'app',
    template: App
})
I kind of doubt there will ever be a Vue renderer for ASR, since Vue has what looks like a solid nested routing library already. There might be call for it, though.
Someone using ASR on an existing app could decide they want to start transitioning to Vue, and they could have ASR mount some Vue states or some Svelte or Riot states, or whatever they were transitioning away from
GavinRay97
@GavinRay97
vue-state-renderer
library-that-you-could-make
-adapter-library-for-library-that-you-could-make
=/
Josh Duff
@TehShrike
But you can imagine any view/templating library in there for that example - all renderers expose the same API
GavinRay97
@GavinRay97
Speaking purely theoretically, is it possible to make a framework agnostic state-management library?
Josh Duff
@TehShrike
I think it would be difficult, because the main differentiator for state libraries isn't how they push data to the components, but how you send state changes to them
with some libraries, you mutate magic objects directly, and the state library watches for changes
GavinRay97
@GavinRay97
You couldn't use some sort of global event bus?
or something built in to HTML5
Josh Duff
@TehShrike
with others, you call dispatch actions with objects representing the state change
well, I like to use a global event bus a lot of the time https://github.com/TehShrike/mannish
but usually if you're hooking up to a state library you want the components to interact with it directly
GavinRay97
@GavinRay97

For example:
store.js

import {fetchJSON, mutateArray} from './utils';
export default {
  fetchJSON: fetchJSON,
  mutateArray: mutateArray,
  syntaxHighlight: syntaxHighlight,
    todoStore:{
      todos: ['Example 1', 'Example 2', 'Example 3'],
      users: [],
    },
}

utils.js

const fetchJSON = async(url) => { return ( await fetch(url).then(r => r.json() ) )}
const mutateArray = async(storeVar, array) => { return array.map(item => storeVar.push(item)) }
export { fetchJSON, mutateArray}

Todo.vue

<template>
  <div>
    <h1 id="title">Global Store State</h1>
    <pre id="highlight-code" v-html="formattedStore" />
    <div id="list-container">
    <div class='list animated tada'>
      <h1>
        To-do List
      </h1>
      <ul v-if="todoStore.todos && todoStore.todos.length">
        <li v-for="(todo, index) in todoStore.todos" @click="emitEvent('removeTodo', index)">
          <a href='#'>
            <i class='icon ion-android-done'></i>
          </a>
          {{todo}}
        </li>
      </ul>
     </div>
     <div class="webflow-style-input">
         <input  placeholder="Add todo's here" v-model="todoInput"></input>
         <button @click="emitEvent('addTodo')"><i class="icon ion-android-arrow-forward"></i></button>
       </div>
   </div>
  </div>
</template>

<script>
import todoController from '../store/controllers/todoController';
export default {
  name: 'Todo',
  store: ['todoStore'],
  events: todoController.events,
  methods: todoController.methods,
  computed: {
    formattedStore() {
      return this.$store.syntaxHighlight(JSON.stringify(this.$store, undefined, 4));
    }
  },
  created() {
    this.fetchUsers();
  }
}
</script>

todoController.js

export default {
  events: {
    addTodo: function() {
      this.todoStore.todos.push(this.todoInput)
      this.todoInput = ''
    },
    removeTodo: function(index) {
      this.todoStore.todos.splice(index, 1)
    },
    setUsers: function(userList) {
      this.$store.mutateArray(this.todoStore.users, userList);
    }
  },
 methods: {
    emitEvent: function(eventName, payload) {
      this.$events.emit(eventName, payload)
    },
    fetchUsers: async function() {
      this.emitEvent('setUsers', await this.$store.fetchJSON('http://jsonplaceholder.typicode.com/users'))
    }
  }
}
todoapp1.png
todoapp3.PNG