Introduction to store
Simple Reducer
As it has already been said, the application state will be held by a Redux store. To create a Redux store, we first need to define a reducer. A reducer is a function which takes the application state and an action, and returns a new version of the application state.
To keep things simple for now, we will create a simple reducer which always return the application state from the previous section (we do not value the action for the moment):
function simpleReducer(state, action) {
return {
codeListById: {
code_list_1: { //we will actually use random ids
label: 'mood',
codes: ['code_1', 'code_2', 'code_3']
},
...
},
codeById: {
code_1: {
label: 'unhappy',
},
...
}
}
}
Set up
We can then bootstrap the application:
- we build a Redux store with the Redux
createStore
function which takes the reducer as its first argument; - we wrap the
CodeListEditor
component with the Provider component from React Redux; this will make the store available to each component in the application through the React Redux connect mechanism.
See bootstraping the application for a more detailed presentation of these steps.
import { createStore } from 'redux'
import { Provider } from 'react-redux'
const store = createStore(simpleReducer)
ReactDOM.render(
<Provider store={store}>
<CodeListEditor id="code_list_1" />
</Provider>,
document.getElementById('base')
)
Notice we passed some props to the code list editor: we provided the id
of the code list we want to edit.
Connect
With this set up, we can now connect the CodeListEditor
component to the store.
import { connect } from 'react-redux'
//The codes will be passed to the `CodeListEditor` through the `connect`
//mechanism. We renamed our `CodeListEditor` function to `CodeListEditorDumb`
//to differentiate it from the component which will be eventually exported
//(see last line).
function CodeListEditorDumb({ codes }) {
return (
<div>
<button onClick={() => console.log('trying to add a code')}>
Add a code
</button>
<div>
{
codes.map(({ id, label }, i) =>
<CodeEditor
key={id} label={label}
handleChange={val => console.log('a code has changed', val)} />)
}
</div>
</div>
)
}
//`mapStateToProps` will extract the codes from the state. Its second argument
//(`ownProps`) is the component props. These props were passed through
// `<CodeListEditor id="code_list_1" />`in the set up. Hence, it is an object
//with an entry called `id`.
const mapStateToProps = (state, ownProps) => {
//code list id
const codeListId = ownProps.id
//For a code list with a given id, we first need to extract an array with
//the ids this code list is made of.
const codeIds = state.codeListById[codeListId].codes
//Then, for each code, we extract some detailed information from the state
//through the `codesById` entry. Since `CodeEditor` expects a code to look
//like `{id: 'code_1', label: 'unhappy' }`, we build the codes according to
//this requirement.
return codeIds.map(id => ({
id: id,
label: state.codeById[id].label
}))
}
export default connect(mapStateToProps)(CodeListEditorDumb)
Notice that the CodeListEditorDumb
expects to be passed an array of codes
, but
when we instantiate the CodeListEditor
within the Provider
with <CodeListEditor id="code_list_1" />
, we passed it the id of the code list. Taking this id
and returning the corresponding list of codes is what mapStateToProps
will take care of. Then, connect
will use mapStateToProps
to wrap the initial component into a higher order component, which given some id
, will retrieve the codes from the application state, and render the initial component with these codes passed as a prop.
In practice, we don't need to rename our initial component CodeListEditorDumb
, since this name is only used locally (in the connect call at the end of the file). See export default to learn more about how exports work.
Our CodeListEditor
will now be able to get the information directly from the store. But when we try to add or edit a code, nothing happens except for the logged information in the console. In the next sections, we will see how to use actions to make things happen.
You can play with this pen