2015-09-19 22:38:36 +00:00
|
|
|
---
|
|
|
|
title: Redux
|
2015-11-24 05:09:17 +00:00
|
|
|
category: React
|
2018-01-17 09:02:23 +00:00
|
|
|
updated: 2018-01-17
|
2017-08-30 13:43:58 +00:00
|
|
|
weight: -3
|
2015-09-19 22:38:36 +00:00
|
|
|
---
|
|
|
|
|
2017-08-30 13:43:58 +00:00
|
|
|
### Creating a store
|
2015-09-19 22:38:36 +00:00
|
|
|
|
|
|
|
```js
|
2017-08-30 13:43:58 +00:00
|
|
|
import { createStore } from 'redux'
|
|
|
|
```
|
|
|
|
{: .-setup}
|
|
|
|
|
|
|
|
```js
|
|
|
|
// Reducer
|
|
|
|
function counter (state = { value: 0 }, action) {
|
2015-09-19 22:38:36 +00:00
|
|
|
switch (action.type) {
|
|
|
|
case 'INCREMENT':
|
2017-08-30 13:43:58 +00:00
|
|
|
return { value: state.value + 1 }
|
2015-09-19 22:38:36 +00:00
|
|
|
case 'DECREMENT':
|
2017-08-30 13:43:58 +00:00
|
|
|
return { value: state.value - 1 }
|
2015-09-19 22:38:36 +00:00
|
|
|
default:
|
2017-08-30 13:43:58 +00:00
|
|
|
return state
|
2015-09-19 22:38:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
```js
|
2017-08-30 13:43:58 +00:00
|
|
|
let store = createStore(counter)
|
|
|
|
```
|
2015-09-19 22:38:36 +00:00
|
|
|
|
2017-08-30 13:43:58 +00:00
|
|
|
```js
|
|
|
|
// Optional - you can pass `initialState` as a second arg
|
|
|
|
let store = createStore(counter, { value: 0 })
|
|
|
|
```
|
|
|
|
|
|
|
|
A store is made from a reducer function, which takes the current `state`, and
|
|
|
|
returns a new `state` depending on the `action` it was given.
|
|
|
|
|
|
|
|
### Using a store
|
|
|
|
|
|
|
|
```js
|
|
|
|
let store = createStore(counter)
|
|
|
|
```
|
|
|
|
{: .-setup}
|
|
|
|
|
|
|
|
```js
|
|
|
|
// Dispatches an action; this changes the state
|
|
|
|
store.dispatch({ type: 'INCREMENT' })
|
|
|
|
store.dispatch({ type: 'DECREMENT' })
|
|
|
|
```
|
|
|
|
|
|
|
|
```js
|
|
|
|
// Gets the current state
|
2015-09-19 22:38:36 +00:00
|
|
|
store.getState()
|
|
|
|
```
|
|
|
|
|
2017-08-30 13:43:58 +00:00
|
|
|
```js
|
|
|
|
// Listens for changes
|
|
|
|
store.subscribe(() => { ... })
|
|
|
|
```
|
|
|
|
|
|
|
|
Dispatch actions to change the store's state.
|
|
|
|
|
|
|
|
## React Redux
|
|
|
|
|
|
|
|
### Provider
|
|
|
|
|
|
|
|
```js
|
|
|
|
import { Provider } from 'react-redux'
|
|
|
|
```
|
|
|
|
{: .-setup}
|
2015-09-19 22:38:36 +00:00
|
|
|
|
|
|
|
```js
|
|
|
|
React.render(
|
|
|
|
<Provider store={store}>
|
2017-03-11 21:18:38 +00:00
|
|
|
<App />
|
2015-09-19 22:38:36 +00:00
|
|
|
</Provider>, mountNode)
|
|
|
|
```
|
|
|
|
|
2017-08-30 13:43:58 +00:00
|
|
|
The `<Provider>` component makes the store available in your React components. You need this so you can use `connect()`.
|
|
|
|
|
|
|
|
### Mapping state
|
|
|
|
|
|
|
|
```js
|
|
|
|
import { connect } from 'react-redux'
|
|
|
|
```
|
|
|
|
{: .-setup}
|
|
|
|
|
2015-09-19 22:38:36 +00:00
|
|
|
```js
|
2017-08-30 13:43:58 +00:00
|
|
|
// A functional React component
|
2017-10-18 23:16:20 +00:00
|
|
|
function App ({ message, onMessageClick }) {
|
2017-08-30 13:43:58 +00:00
|
|
|
return (
|
|
|
|
<div onClick={() => onMessageClick('hello')}>
|
|
|
|
{message}
|
2017-03-11 21:18:38 +00:00
|
|
|
</div>
|
2017-08-30 13:43:58 +00:00
|
|
|
)
|
2015-09-19 22:38:36 +00:00
|
|
|
}
|
2017-08-30 13:43:58 +00:00
|
|
|
```
|
2015-09-19 22:38:36 +00:00
|
|
|
|
2017-08-30 13:43:58 +00:00
|
|
|
```js
|
|
|
|
// Maps `state` to `props`:
|
|
|
|
// These will be added as props to the component.
|
|
|
|
function mapState (state) {
|
2015-09-19 22:38:36 +00:00
|
|
|
return { message: state.message }
|
|
|
|
}
|
|
|
|
|
2017-08-30 13:43:58 +00:00
|
|
|
// Maps `dispatch` to `props`:
|
|
|
|
function mapDispatch (dispatch) {
|
2017-03-11 21:18:38 +00:00
|
|
|
return {
|
|
|
|
onMessageClick (message) {
|
|
|
|
dispatch({ type: 'click', message })
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-30 13:43:58 +00:00
|
|
|
// Connect them:
|
|
|
|
export default connect(mapState, mapDispatch)(App)
|
|
|
|
```
|
|
|
|
|
|
|
|
### Shorthand
|
|
|
|
|
|
|
|
```js
|
|
|
|
export default connect(
|
|
|
|
(state) => ({
|
|
|
|
message: state.message
|
2017-12-14 06:13:25 +00:00
|
|
|
}),
|
2017-08-30 13:43:58 +00:00
|
|
|
(dispatch) => ({
|
|
|
|
onMessageClick: (message) => {
|
|
|
|
dispatch({ type: 'click', message })
|
|
|
|
}
|
|
|
|
})
|
|
|
|
)(App)
|
2017-03-11 21:18:38 +00:00
|
|
|
```
|
|
|
|
|
2017-08-30 13:43:58 +00:00
|
|
|
Same as above, but shorter.
|
|
|
|
|
2018-01-17 09:02:09 +00:00
|
|
|
### Combining reducers
|
|
|
|
|
|
|
|
```js
|
|
|
|
const reducer = combineReducers({
|
|
|
|
counter, user, store
|
|
|
|
})
|
|
|
|
```
|
|
|
|
|
|
|
|
Combines multiple reducers into one reducer function. See: [combineReducers](https://redux.js.org/docs/api/combineReducers.html) _(redux.js.org)_
|
|
|
|
|
2017-03-11 21:18:38 +00:00
|
|
|
## Middleware
|
|
|
|
|
2017-08-30 13:43:58 +00:00
|
|
|
### Signature
|
|
|
|
|
2017-03-11 21:18:38 +00:00
|
|
|
```js
|
|
|
|
// noop middleware
|
|
|
|
const logger = store => dispatch => action { dispatch(action) }
|
2017-08-30 13:43:58 +00:00
|
|
|
```
|
2017-03-11 21:18:38 +00:00
|
|
|
|
2017-08-30 13:43:58 +00:00
|
|
|
```js
|
2017-03-11 21:18:38 +00:00
|
|
|
const logger = store => {
|
|
|
|
// This function runs on createStore().
|
|
|
|
// It returns a decorator for dispatch().
|
|
|
|
|
|
|
|
return dispatch => {
|
|
|
|
// Runs on createStore(), too.
|
|
|
|
// It returns a new dispatch() function
|
|
|
|
|
|
|
|
return action => {
|
|
|
|
// Runs on every dispatch()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
2017-08-30 13:43:58 +00:00
|
|
|
Middlewares are simply decorators for `dispatch()` to allow you to take
|
|
|
|
different kinds of actions, and to perform different tasks when receiving
|
|
|
|
actions.
|
|
|
|
|
2017-03-11 21:18:38 +00:00
|
|
|
### Applying middleware
|
|
|
|
|
|
|
|
```js
|
2017-08-30 13:43:58 +00:00
|
|
|
const enhancer = applyMiddleware(logger, thunk, ...)
|
|
|
|
```
|
|
|
|
|
|
|
|
```js
|
|
|
|
const store = createStore(reducer, {}, enhancer)
|
2015-09-19 22:38:36 +00:00
|
|
|
```
|
2017-08-30 13:43:58 +00:00
|
|
|
{: data-line="1"}
|
2015-09-19 22:38:36 +00:00
|
|
|
|
2017-08-30 13:43:58 +00:00
|
|
|
## References
|
|
|
|
{: .-one-column}
|
2015-09-19 22:38:36 +00:00
|
|
|
|
2017-08-30 13:43:58 +00:00
|
|
|
* [Redux](https://www.npmjs.com/package/redux) _(npmjs.com)_
|
|
|
|
* [React-redux](https://www.npmjs.com/package/react-redux) _(npmjs.com)_
|
|
|
|
* [Usage with React](http://redux.js.org/docs/basics/UsageWithReact.html) _(redux.js.org)_
|
|
|
|
{: .-also-see}
|