Action nodes
Since Flower follows Redux patterns, you dispatch actions either to update your state or to trigger side effects, that are handled with sagas (see Redux Saga).
Sometimes in a flower you just want to dispatch an action, without having the dispatching logic bound to a specific component (for instance bound to a button click). In this kind of situation, it is useful to create an action node, whose only purpose is to dispatch an action; it can also be reused elsewhere, everytime that action needs to be dispatched.
Creating an action
An action node is ultimately a React component that returns null or maybe a loader, and dispatches the desired action as soon as it is mounted (via a useEffect hook).
To be available in the Flower interface, it must be registred with Flower.registerComponents() and must have its flower.json configuration, with the key isAction set to true.
This is a basic example of an action node:
{
"type": "component",
"isAction": true,
"name": "FetchUsers",
"title": "Fetch users",
"category": "actions",
"editing": [],
"output": {
"error.message": "text",
"success": "bool"
}
}
const FetchUsers = ({ flowName, reducerName }) => {
const dispatch = useDispatch()
useEffect(() => {
dispatch({
type: 'users/fetchUsers',
payload: { flowName, reducerName }
})
}, [])
return null
}
export default FetchUsers
Moving to the next node
The action users/fetchUsers will likely be intercepted by a saga, that will perform the desired side effect (getting a list of users); when done, it must notify Flower that it can proceed to the next node in the flower.
To do this, the saga dispatches a special action type flower/next with the name of the flower to advance in (that is why the original action included the flower name and the reducer name).
Following with the example, this might be the related saga:
function* fetchUsers(action) {
const { flowName } = action.payload
// Fetch users and maybe save the list to your store
yield put({ type: 'flower/next', payload: { flowName } })
}
export default function* userSaga() {
yield takeEvery('users/fetchUsers', fetchUsers)
}
Now you have an action node named Fetch users that will retrieve a list of users, maybe save it to the store so other components can make use of it, and finally move the current flower to the next node. This node can be reused independently because it is not bound to any specific component.