GithubHelp home page GithubHelp logo

state-router-redux-ractive's Introduction

I made this because I wanted to use Redux to drive some of my complicated-document views implemented with the abstract-state-router.

Using it in theory

You initialize it with a state router and optional middlewares. It doesn't list any version of Redux in the package.json - it will use whatever version you add as a dependency to your project.

On any of your state, you can specify an optional initial state, reducer function, and even a function to run after the reducer step where you make any other side effects happen that you need to.

Ractive

This module is made to work with RactiveJS, but as you can see from the implementation, the coupling is very light. I would like to make it nonexistent in the future if possible.

If you are using the abstract-state-router with a different templating system and want to use Redux, fork this module - if your DOM library uses something instead of on to catch events, you'll need to make that change, otherwise the only thing you may need to change is the set method that takes the state object and applies it to the DOM object.

If you are using Ractive, just make sure to set twoway: false to disable two-way binding.

Using it in practice

npm install state-router-redux-ractive

Initialization requires only calling the function and passing in a state router:

var Ractive = require('ractive')
var ractiveRenderer = require('ractive-state-router')
var StateRouter = require('abstract-state-router')
var routerRedux = require('state-router-redux-ractive')

var renderer = ractiveRenderer(Ractive)
var stateRouter = StateRouter(, 'body')

routerRedux(stateRouter)

You can associate a reducer function with any of your states by adding a reducer property to the data property of any state. Any state with a reducer can have also have an initialState, and/or an afterAction property.

stateRouter.addState({
	name: 'app.topics',
	route: '/topics',
	template: {
		template: require('fs').readFileSync('implementations/ractive-redux/app/topics/topics.html', { encoding: 'utf8' }),
		twoway: false
	},
	resolve: function(data, parameters, cb) {
		all({
			topics: model.getTopics,
			tasks: model.getTasks
		}, cb)
	},
	data: {
		initialState: {
			tasksUndone: {},
			addingTopic: false
		},
		reducer: reducer,
		afterAction: switchForNamedArgs({
			START_ADDING_TOPIC: ({ domApi: ractive }) => ractive.find('.new-topic-name').focus(),
			ADD_TOPIC: ({ state, dispatch }) => state.topics.forEach(
					topicId => recalculateTasksLeftToDoInTopic(topicId, dispatch))
		})
	}
}

To see a "real-life" example, check out this demo state in the state-router-example.

The properties of data that are used:

  • initialState: whatever you want Redux to be initialized with. Any properties returned by the resolve function will be applied to the initial state, overwriting any duplicate properties.
  • reducer: any regular Redux reducer function. Will be passed straight to Redux.
  • afterAction: called immediately after the reducers changes are applied to the store (synchronously). Passed these arguments:
    • state - the store's new value after the reducer call
    • dispatch - the dispatch function of the store
    • domApi - the active DOM API of the state. A Ractive instance, in my case.
    • action - the action object that caused the whole kerfuffle

How to dispatch actions?

These examples are Ractive, but whatever mechanism your DOM library uses for emitting events will work here. Dispatch actions from your Ractive template like so:

<button on-click="fire('dispatch', 'SET_TASK_DONE', { index: i, done: false })">
	Restore
</button>

To emit an action with the current contents of an input element, you can emit the dispatchInput event:

<input type="text" on-change="fire('dispatchInput', 'SET_NEW_TOPIC', event.node)">

The second event argument must be the DOM element object itself. The library will grab the value off of it for you (using dom-value) and put that value on the payload property of the action sent to the reducer.

Those are the only two events handled at the moment. I'm not sure if any more will be necessary/handy - we'll see!

Develop/test

git clone https://github.com/TehShrike/state-router-redux-ractive.git
cd state-router-redux-ractive
npm install
npm test

Suggestions welcome.

Since this project is the glue between three sizeable libraries, I don't want to load it down with a bunch of features, but I would love to talk over any ways it could be simplified, or changed to better suit its purpose.

Open an issue or ping me on Twitter if you have any thoughts or questions!

License

WTFPL

state-router-redux-ractive's People

Contributors

tehshrike avatar daytonlowell avatar

Stargazers

 avatar  avatar Łukasz Korecki avatar RYeah Sh avatar Петър Денев (Peter Denev) avatar Tobias Davis avatar

Watchers

 avatar James Cloos avatar  avatar shtanko.michael avatar  avatar

Forkers

daytonlowell

state-router-redux-ractive's Issues

Split core into new repo, make a Riot version

This shouldn't be Ractive-specific. Most of it can be moved directly to a new repo, with these options added:

  • the event-firing methods (on and fire in Ractive's case)
  • an applyDataToTemplate method would need to be passed in - it would need to take the domApi, the last state, and the current state. The Ractive implementation would pass in a function containing
var smartSet = ractiveSmartDiff(last || {}, newState)
ractiveSmartDiff.apply(domApi, smartSet)

The Riot implementation would be something like

domApi.opts = newState
domApi.update()

This Ractive-specific repo can maintain its API, but I'm not even sure it's worth making another one for Riot, since the Riot usage could be just a few lines to copy/paste from the readme.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.