Actions & Reducers#
In this chapter we are going to create a custom content type. We will create an FAQ content type. We will then create a custom action and reducer to fetch this content type.
We start by creating the content type at: http://localhost:8080/Plone/dexterity-types.
We select Add New Content Type...
and enter Faq
as Type Name
and faq
as Short Name
.
When we select the Faq
item and go to the Fields
tab we can see we already have the Dublin Core fields.
We are going to use the title for the question and the description for the answer.
In the root of the Plone site we will create a folder called FAQ
with some FAQ items in there.
Creating The Action#
To create an action we will first add the action type to constants/ActionTypes.js
.
export const GET_FAQ = 'GET_FAQ';
Next we will create a file for our action at actions/faq/faq.js
/**
* Faq actions.
* @module actions/faq/faq
*/
import { GET_FAQ } from '../../constants/ActionTypes';
/**
* Get FAQ items.
* @function getFaq
* @returns {Object} Faq action.
*/
export function getFaq() {
return {
type: GET_FAQ,
request: {
op: 'get',
path: `/@search?portal_type=faq`,
},
};
}
And we will add the actions to the actions/index.js
file.
import { getFaq } from './faq/faq';
export { getFaq };
Creating The Reducer#
Next we will create the reducer by creating the reducers/faq/faq.js
file.
/**
* Faq reducer.
* @module reducers/faq/faq
*/
import { map } from 'lodash';
import { settings } from '~/config';
import { GET_FAQ } from '../../constants/ActionTypes';
const initialState = {
error: null,
items: [],
loaded: false,
loading: false,
};
/**
* Faq reducer.
* @function faq
* @param {Object} state Current state.
* @param {Object} action Action to be handled.
* @returns {Object} New state.
*/
export default function faq(state = initialState, action = {}) {
switch (action.type) {
case `${GET_FAQ}_PENDING`:
return {
...state,
error: null,
loading: true,
loaded: false,
};
case `${GET_FAQ}_SUCCESS`:
return {
...state,
error: null,
items: map(action.result.items, item => ({
...item,
'@id': item['@id'].replace(settings.apiPath, ''),
})),
loaded: true,
loading: false,
};
case `${GET_FAQ}_FAIL`:
return {
...state,
error: action.error,
items: [],
loading: false,
loaded: false,
};
default:
return state;
}
}
And we will add the faq
reducer to the root reducer at reducers/index.js
.
/**
* Root reducer.
* @module reducers/root
*/
import defaultReducers from '@plone/volto/reducers';
import faq from './faq/faq';
/**
* Root reducer.
* @function
* @param {Object} state Current state.
* @param {Object} action Action to be handled.
* @returns {Object} New state.
*/
const reducers = {
...defaultReducers,
faq,
};
export default reducers;
Exercise#
Add the faq_view
as an available view to the Folder
content type at http://localhost:8080/Plone/portal_types/Folder/manage_propertiesForm.
Set the faq_view
for the folder at http://localhost:3000/faq
.
Create the faq_view
in Volto and use the actions and reducers created above.