Dead simple tool moving component local state to a Redux store namespace.
npm install --save redux-namespace
Transient state like toggles and form input require too much boiler plate.
redux-namespace
helps you connect your component with a trivial key value store. This solves the
far–too–painful/should–be–easier problems with managing view state after routing.
To get the incredible time traveling super powers and retained transients provided from having complete hydration of your app state. Time travel is fun, play with this.
Redux Namespace builds on React Redux,
but provides new methods: assign
, cursor
and select
to go with dispatch
.
- Calling
assign(key, value)
puts a value in your namespace andselect(key)
gets it out. - Calling
select()
with no parameters returns the entire namespace. - Calling
cursor(key)
returns a nested namespace.
Connecting your components with their own namespace is trivial. Use it like React Redux, but forget about writing the selectors.
namespace.connect('recipe/editor')(Component)
npm install --save redux-namespace
import { createStore, combineReducers } from 'redux';
import namespace from 'redux-namespace';
const store = createStore(combineReducers({namespace}));
import React, {View, Text, TextInput, TouchableHighlight, } from 'react-native'
import namespace from 'redux-namespace/native';
// If decorators are your thing
@namespace.connect('component/namespace')
class Form extends React.Component {
static propTypes = {...namespace.shape}
render () {
let {select, assign, dispatch} = this.props;
return (
<View>
<TextInput
value={select('email')} onChange={assign('email')}/>
<TextInput
value={select('password')} onChange={assign('password')}/>
<TouchableHighlight onPress={e => dispatch(someAction(select()))}>
<Text>Submit</Text>
</TouchableHighlight>
</View>
)
}
}
import React from 'react'
import namespace from 'redux-namespace';
class Form extends React.Component {
static propTypes = {...namespace.shape}
render () {
let {select, assign, dispatch} = this.props;
return (
<form onSumbit={() => dispatch(someAction(select()))}/>
<input
value={select('email')}
onChange={e => assign('email', e.target.value)}/>
<input
value={select('password')}
onChange={e => assign('password', e.target.value)}/>
</form>
)
}
}
// Or, if decorators aren't your thing
export namespace.connect('component/namespace')(Form)
<Route path='free-pizza'
component={ namespace.connect('pizza-surplus')(Component) }/>
Automatically wrap your routes by assigning them after they're made.
let routes = [
<Route/>
<Route/>
<Route/>
]
routes = routes.map(route => namespace.connect(route.path)(route))
@namespace.connect('recipes')
class RecipeEditor extends React.Component {
static propTypes = {...namespace.shape}
render () {
let document = namespace.connect(`recipes/${select('currentId')}`);
let autosave = namespace.connect(`recipes/${select('currentId')}/autosave`);
let groceries = namespace.connect('groceries');
let Loader = document(Await)
let Autosave = document(autosave(DebouncedSave))
return (
<Loader>
<Autosave/>
{ map(React.createElement,
map(document, [
Menu,
WYSIWYG,
Editor,
WordCount,
groceries(VegetableCount),
groceries(CalorieCount),
groceries(CountChoculaCount)
]))
}
</Loader>
)
}
}
Using the namespace.BIND
constant you can write new reducers to work with
your events without adding more plumbing.
function (state, action) {
if (action.type === namespace.BIND) {
let {namespace, key, value} = action.payload;
switch (namespace) {
case 'app/signup':
state[namespace][key].error = validate(key, value.field);
break;
case 'my/easter/egg':
if (key === 'menuToggle')
if (++state.finalCountdown > 5)
state.surpriseCatGif = true
break;
}
// I'm not sure which is more esoteric, the previous example or this one
if (state.namespace[namespace][ttl] > new Date() - state[ttl][action.namespace][key])
delete state.namespace[namespace][key];
}
return state;
}
Although you probably shouldn't do this often, it's faster than scaffolding the additional constants and action creators. Beware, with great power comes greater side effects… that we probably should avoid unless we liked Angular 1—better known as Whoopsie Daisy.
MIT