React +redux reduce(), filter(), map(), some(), every()… A property

Today we’ll learn by reading the official sample code for Redux-Undo, using undo, DevTools, and Router in Redux.

example

This example is a counter program that contains the counter, the Redux development tool on the right, and a route (but only the “/” address).

The source code:

Github.com/lewis617/re…

undo

Implementing the undo feature is very simple, you just need to make your Reducers undo. What does that mean? Look at the code

reducers/index.js

import { combineReducers } from 'redux' import counter from './counter' import { INCREMENT_COUNTER, DECREMENT_COUNTER, UNDO_COUNTER, REDO_COUNTER } from '.. /actions/counter' import undoable, { includeAction } from 'redux-undo' const rootReducer = combineReducers({ counter: undoable(counter, { filter: includeAction([INCREMENT_COUNTER, DECREMENT_COUNTER]), limit: 10, debug: true, undoType: UNDO_COUNTER, redoType: REDO_COUNTER }) }) export default rootReducerCopy the code

We use undoable and includeAction provided by redux-undo to add the undo function to the reducer (counter). “Filter” is to select what actions are available for filtering, so we just decremented INCREMENT_COUNTER, “DECREMENT_COUNTER” is INCREMENT_COUNTER, “limit” is limit, “debug” is whether to debug code, Undotype and redotype are undo redo actions.

So all I need to do is trigger the undo redo action to undo the redo, that’s it!

devtools

Next, let’s learn how to use devTools. What is DevTools? Devtools is really components. What does DevTools do? Devtools can help us see the state of the entire application and log the actions triggered by the entire application. How do we install DevTools? First of all, we know devTools is a component, so can’t we just render DevTools in a container?

containers/DevTools.js

/*eslint-disable*/
import React from 'react'
import { createDevTools } from 'redux-devtools'
import LogMonitor from 'redux-devtools-log-monitor'
import DockMonitor from 'redux-devtools-dock-monitor'
/*eslint-enable*/

export default createDevTools(
  
    
  
)Copy the code

This is reusable container code, which means you can just copy and paste this JS file into your project. This code outputs a DevTools component.

containers/Root.js

/* global __DEVTOOLS__ */ /*eslint-disable*/ import React, { Component, PropTypes } from 'react' import { Provider } from 'react-redux' import { Router } from 'react-router' import configureStore from '.. /store/configureStore' import routes from '.. /routes' /*eslint-enable*/ const store = configureStore() function createElements (history) { const elements = [ ] if (typeof __DEVTOOLS__ ! == 'undefined' && __DEVTOOLS__) { /*eslint-disable*/ const DevTools = require('./DevTools') /*eslint-enable*/ elements.push() } return elements } export default class Root extends Component { static propTypes = { history: PropTypes.object.isRequired } render () { return (
        
{createElements(this.props.history)}
)}}Copy the code

In this code, we place our exported DevTools component under the Router component, but we add a typeof __DEVTOOLS__! == ‘undefined’ && __DEVTOOLS__, if the condition is true, we will render DevTools, otherwise not. By doing this, we mean that we can parameterically control devTools to display in the development environment and not in production.

Should I just render it? Of course not! We also need to register in the store!

store/configureStore.js

/* global __DEVTOOLS__ */ import { createStore, applyMiddleware, compose } from 'redux' // reducer import rootReducer from '.. /reducers' // middleware import thunkMiddleware from 'redux-thunk' import promiseMiddleware from 'redux-promise' import createLogger from 'redux-logger' const loggerMiddleware = createLogger({ level: 'info', collapsed: true }) const enforceImmutableMiddleware = require('redux-immutable-state-invariant')() let createStoreWithMiddleware if  (typeof __DEVTOOLS__ ! == 'undefined' && __DEVTOOLS__) { const { persistState } = require('redux-devtools') const DevTools = require('.. /containers/DevTools') createStoreWithMiddleware = compose( applyMiddleware( enforceImmutableMiddleware, thunkMiddleware, promiseMiddleware, loggerMiddleware ), DevTools.instrument(), persistState(window.location.href.match(/[?&]debug_session=([^&]+)\b/)) )(createStore) } else { createStoreWithMiddleware = compose( applyMiddleware(thunkMiddleware, promiseMiddleware) )(createStore) } /** * Creates a preconfigured store. */ export default function configureStore (initialState) { const store = createStoreWithMiddleware(rootReducer, initialState) if (module.hot) { // Enable Webpack hot module replacement for reducers module.hot.accept('.. /reducers', () => { const nextRootReducer = require('.. /reducers/index') store.replaceReducer(nextRootReducer) }) } return store }Copy the code

That’s it, devTools is installed, simple as that! Just render it out and put it under the whole program!

store enhancer

This line of devTools.instrument () makes DevTools usable! Some students will ask, what the hell is instrument()? It’s officially called store Enhancer, which translates to store enhancer and is in the same category as Applymiddleware, both store enhancers. So what does the Store enhancer do? The Store Enhancers can be used to create a new store that replaces the base store and allows you to add a lot of functionality to your application. Appllymiddleware, for example, can add middleware to your Redux, enabling async functionality, logging, etc.

enforceImmutableMiddleware,thunkMiddleware, promiseMiddleware, loggerMiddleware

Some students will ask,enforceImmutableMiddlewareWhat is? What’s it for? This use prohibits you from changing state. What? How can we update the state without changing the state? Redux does not allow you to change the state. In reducer we must return a new state instead of modifying the original state!

What is thunk? Thunk We’ll talk about thunk in React + Redux connect, applyMiddleware, Thunk, webpackHotMiddleware.

So what is promiseMiddleware? This is middleware that, like Thunk, enables your actions to be asynchronous. However, we can see that we don’t use thunk and in this examplepromiseMiddlewareThese two middleware, this example is a seed file, can be expanded on this basis, so the author wrote two common middleware in advance, easy for us to use in the future!

thenloggerMiddlewareWhat is it for? As the name implies, is used for logging, when you add this middleware, you can see the related print log on the command line! Of course you can run the application, remove the middleware, to see how it works!

instrument()And compose () method

Unlike Applymiddleware, Instrument () can only be used in development environments and can only enable your DevTools components! So we separate Applymiddleware from instrument with a comma. Why? Compose this is the compose method, which is used instead of nesting functions.

router

In short, the Router is also a component, a multi-view component, that can switch views by switching urls, but it’s still a component. Since it’s a component, we just need to render it!

At the top level we’re going to render a Router, and the code is in containers/ root.js, so we’re not going to list the code again.

Then we start rendering each view. Here we have only one view, the one with the directory “/”, and we render it!

routes.js

/*eslint-disable*/
import React from 'react'
import { Route } from 'react-router'
import App from './containers/App'
import * as containers from './containers'
/*eslint-enable*/

const {
  CounterPage
} = containers

export default (
  
    
  
)Copy the code

We export a view whose component is CounterPage. It’s that simple!

We then render it into the Router component on containers/ root.js!

Copy the code

We can see that we do not put devTools in the routing component. This means that devTools will always render no matter how you switch views!

Of course, there are many other APIS for react-Router. We only use a few of them. I don’t recommend reading the API documentation.

Tutorial source code and directory

If you find this blog tutorial helpful, give yourself a star!

Github.com/lewis617/re…