Actions
This is part of the wrap
API. It is one of the keys you can supply to the configuration object. If you are unsure what this means, look at the wrap
API docs.
In coflux, Actions are colocated with your components. While traditional flux separates actions from components, coflux takes the "declarative" approach. Insisting an action ties to a component. This means you may duplicate code across a couple actions. We think that is okay, as it is more declarative, simpler to reason about, and less searching day-to-day.
In the configuration object, actions
are an object of key value pair functions. These functions become props for your component on the props.actions
key. Each action has the following signature:
action(state:Object, next:Function, ...args:any);
The first argument, state
, is the slice defined by mapStateToProps
. Whatever state gets sliced in the mapStateToProps
gets passed into this function when invoked.
The second argument is how you update state. It is a function which takes an object. The object must have keys that match the keys from your mapStateToProps
return object. That way coflux knows the path to the state you are updating. Let's take an example for this one.
Say this is your state:
const state = {
user: {
firstName: 'Blaine',
},
};
Our component is in an edit mode, updating the first name. Your component that is wrapped
would have a mapStateToProps
like this:
function mapStateToProps() {
return (
firstName: 'user.firstName',
);
}
The key could be anything. It doesn't have to match what is actually in state. But whatever the key's name is, that is what gets passed around. Thus, so at any point in coflux now, firstName
represents the value at user.firstName
. Now if we want to define an action to update the firstName
, define it like this:
const configuration = {
actions: {
/* This event is triggered by a keyboard event */
updateFirstName(state, next, event) {
next({firstName: event.target.value});
}
}
}
This action reads the value input-ed and updates application state. Finishing off the example, here is the component:
function editName({actions, firstName}) {
return (
<input value={firstName} onChange={actions.updateFirstName} />
);
}
Here is everything together:
// app.js
import { Provider } from 'coflux';
import ReactDOM from 'react-dom';
import EditUser from './EditUser';
const state = {
user: {
firstName: 'Blaine',
},
}
ReactDOM.render(
<Provider state={state}>
<EditUser />
</Provider>
, domNode
);
// EditUser/index.js
import { wrap } from 'coflux';
function EditUser({actions, firstName}) {
return (
<input value={firstName} onChange={actions.updateFirstName} />
);
}
export default wrap(EditUser, {
mapStateToProps() {
return (
firstName: 'user.firstName',
);
},
actions: {
/* This event is triggered by a keyboard event */
updateFirstName(state, next, event) {
next({firstName: event.target.value});
},
},
});