npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

react-flux

v1.0.1

Published

A library implementing React Flux data flow

Downloads

88

Readme

Build Status Coverage Status

Read about Flux-Data-Flow

Install

Npm:

$ npm install react-flux

Bower:

$ bower install react-flux

Use it

var ReactFlux = require("react-flux");

Browser:

<script src="/react-flux/dist/react-flux.js" type="text/javascript"></script>

ReactFlux

ReactFlux expose the following methods:
1. createConstants( Array constants, String prefix )
2. createActions( Object actions )
3. createStore( Object mixin, Array listeners )
4. dispatch( String constant, Object payload )
5. mixinFor( Store store, ..... )

Constants

var userConstants = ReactFlux.createConstants([
	'LOGIN',
	'LOGOUT'
], 'USER');

The second parameter which is a prefix to be added to all messages is optional

this will result in the following:

{
	 LOGIN:           'USER_LOGIN',
	 LOGIN_SUCCESS:   'USER_LOGIN_SUCCESS',
	 LOGIN_FAIL:      'USER_LOGIN_FAIL',
	 LOGIN_AFTER:     'USER_LOGIN_AFTER',
	 LOGOUT:          'USER_LOGOUT',
	 ...
}

It is also possible to configure constant generation, one may configure separator, success- and fail suffixes

ReactFlux.configs.constants.setSeparator(':');
ReactFlux.configs.constants.setSuccessSuffix('OK');
ReactFlux.configs.constants.setFailSuffix('ERROR');
ReactFlux.configs.constants.setAfterSuffix('DONE');

now the previous example will result in:

{
	 LOGIN:            'USER:LOGIN',
	 LOGIN_OK:         'USER:LOGIN:OK',
	 LOGIN_ERROR:      'USER:LOGIN:ERROR',
	 LOGIN_DONE:       'USER:LOGIN:DONE',
	 LOGOUT:           'USER:LOGOUT',
	 ...
}

to go back to default configurations use:

ReactFlux.configs.constants.resetToDefaults();

Actions

var userActions = ReactFlux.createActions({
	
	login: [userConstants.LOGIN, function loginAction(username, password){
		return {
			id: 1,
			username: 'Max Mustermann'
		}
	}]
	
});

calling userActions.login("mustermann", "1234567") will do the following:
1. USER_LOGIN gets dispatched directly before the passed callback gets executed. which means: any store handlers registered for USER_LOGIN will get invoked. 2. the passed callback gets executed, in this case loginAction.
3. Depending on the result of the action callback, it will either dispatch USER_LOGIN_SUCCESS or USER_LOGIN_FAIL.
4. USER_LOGIN_AFTER get's dispatched after step 3

USER_LOGIN_SUCCESS gets dispatched in two cases:
1. The callback returns a value, like in the example above
2. the callback returns a promise which gets resolved

USER_LOGIN_FAIL gets dispatched in two cases:
1. The action callback throws an exception or returns an Error
2. It returns a promise which gets rejected

Stores

var userStore = ReactFlux.createStore({
	
	mixins: [ SomeStoreMixin, AnotherStoreMixin ],

	getInitialState: function(){
		return {
			isAuth: false,
			data: null,
			isLoggingIn: false,
			error: null
		};
	},
	
	storeDidMount: function(){
		//Get called when store is ready
	},
	
	isAuth: function(){
		return this.get('isAuth')
	}
	
}, [
 
 /**
	* called directly before executing login action
	*/
 [userConstants.LOGIN, function onLogin(){
	this.setState({
		isLoggingIn: true,
		error: null
	});
 }],
 
 /**
	* called if login action was successful
	*/
 [userConstants.LOGIN_SUCCESS, function onLoginSuccess(payload){
	this.setState({
		isAuth: true,
		data: payload
	});
 }],

 /**
	* called if login action failed
	*/
 [userConstants.LOGIN_FAIL, function onloginFail(error){
	this.setState({
		error: error.message
	});
 }]
 
 /**
	* called after login action succeeds or fails
	*/
 [userConstants.LOGIN_AFTER, function onloginAfter(error){
	this.setState({
		isLoggingIn: false
	});
 }],

]);

ReactFlux.createStore takes two parameters:

1. A mixin object for the store:
	 

Thanks to Leland Richardson store definition accepts mixins which get mixed into the store. A store mixin may be recursive and it may hook into store lifecycle events i.e getInitialState and storeDidMount. Please have a look at the tests for more insights.

2. an array of action listeners

###all *_SUCCESS callbacks get payload as parameter, which is the value returned from an actioin, or the payload passed to it's promise resolve function

###all *_FAIL callbacks get an Error object, or whatever you pass to a promise reject function

###Store API #####store.setState(obj)
sets the state of the store #####store.replaceState(obj) replaces the state of the store #####store.getState() gets the store state. getState does not return a copy or a clone of state, rather it returns the object itself. #####store.getStateClone() gets a clone of the store state #####store.get(key) gets the value corresponding to the key from store's state. get does not return a clone of the value if it's an object, rather it returns the object itself. #####store.getClone(key) gets a clone of the value corresponding to the key from store's state #####store.onChange(callback) registers a callback which gets invoked whenever store's state changes #####store.offChange(callback) deregisters callback from store changes #####store.mixinFor() Each store exposes a "mixinFor" method which returns a ReactMixin, so that you don't need to manually couple your your components with different stores. If you use this mixin you must implement a getStateFromStores method on the component which gets called in componentWillMount and whenever the store's state gets updated

	var fooComponent = React.createClass({
		mixins: [
			fooStore.mixinFor()
		],
		getStateFromStores: function(){
			return {
				fooState: fooStore.getState()
			};
		},
		
	});

#####store.addActionHandler(constant, actionHandlerMixin) register an action handler for the given constant.. please refer to ActionHandlers sections for more details.

#####store.getActionState(constant) returns a copy of the state of the action handler related to the given constant #####store.setActionState(const, newState) sets the state of the action handler related to the given constant

Store Action Handlers

stores also provide a different way for setting handlers, namely through StoreActionHandler. StoreActionHandler is an object defining handlers for all action possible constants. It provides a seperate sub-state specific to every single action handler. This could be useful when maintaining different UI states in a store that is used by different UI views. This way we don't need to pollute a Store's state with many variables correlating to the state of UI Views, we can just dump those variables into sub-states, while keeping store's state dedicated to real data.

UserStore.addActionHandler(constants.SAVE_NEW_USERNAME, {

	//returns initial state specific only to this handler
	getInitialState: function(){
		 isSaving: false,
		 error: null,
		 success: false
	},
		
	//this gets called before the action associated with SAVE_NEW_USERNAME is executed
	before: function(){
		//this inside handler callbacks refers to the action handler itself and not to the store
		this.setState({
		 isSaving: true,
		 error: null
		});
	},
	
	//this gets called after the action associated with SAVE_NEW_USERNAME succeeds or fails
	after: function(){
		this.setState({
			isSaving: false
		});
	},
	
	//this gets called if the action associated with SAVE_NEW_USERNAME succeeds
	success: function(payload){
		this.setState({
			success: true
		});
		
		//here we set the state of parent store(UserStore) using this.parent.setState
		this.parent.setState({
			username: payload.username
		});
	},
	
	//this gets called if the action associated with SAVE_NEW_USERNAME fails
	fail: function(error){
		this.setState({
			error: error
		});
	}
	
});

getInitialState, before, after, success and fail are optional.

We can access handler specific state using:

UserStore.getActionState(constants.SAVE_NEW_USERNAME); // returns the state object

or we can get a specific property from handler state

UserStore.getActionState(constants.SAVE_NEW_USERNAME, 'isSaving');

to reset a handler state use:

UserStore.resetActionState(constants.SAVE_NEW_USERNAME);

to set a handler state use:

UserStore.setActionState(constants.SAVE_NEW_USERNAME, {
 //.....
});

setting handler state will cause the store to emit a change event

Inside an ActionHandler the parent store is accessible through this.parent. So, to update the state of the parent store from within the actionHandler, use this.parent.setState

Code Generation

ReactFlux ships with a code generation utility which can make life a lot easier.
To use this functionality create a special js file in your working directory:

flux.js

#!/usr/bin/env node
require('react-flux/codegen');

make it executable

chmod +x flux.js

then look at the help

./flux --help

code generator will put your files into "flux" directory by default. if you want to change it, create another file "reactflux.json" in the same directory as "flux.js" and specify where you want to have your flux folder

{
	"directory": "my-special-flux-directory"
}

Example React component

var LoginComponent = React.createClass({
	
	mixins: [ 
		ReactFlux.mixinFor(userStore) //or  userStore.mixin() 
	], 
	
	getStateFromStores: function(){
		return {
			user: userStore.state
		};
	},
	
	render: function(){
		if( !this.state.user.get('isAuth') ){
			return this.renderLogin();
		}
		return this.renderLogout();
	},
	
	renderLogin: function(){
		if( this.state.user.get('isLoggingIn') ){
			return (<div>...</div>);
		}
		return(
			<div>
				Hello Stranger! 
				<a href="#" onClick={this.login}>login</a>
			</div>
		);
	},
	
	renderLogout: function(){
		return(
			<div>
			Hello {this.state.user.get('data').username}!
			<a href="#" onClick={this.logout}>Logout</a>
			</div>
		);
	},
	
	login: function(){
		userActions.login("mustermann", "1234567");
		return false;
	},
	
	logout: function(){
		userActions.logout();
		return false;
	}
	
});