React basics 3
12.react-ui
12.1 - the most popular open source React UI component library
a. Material UI (abroad)
1.Official website: http://www.material-ui.com/#/ 2.github: https://github.com/callemall/material-ui
b. Ant Design / ANTD
1.PC Official website: https://ant.design/index-cn 2.Mobile official website: https://mobile.ant.design/index-cn 3.Github: https://github.com/ant-design/ant-design/ 4.Github: https://github.com/ant-design/ant-design-mobile/
12.2 - Introduction to ant design mobile
1. Use create react app to create react application
1.npm install create-react-app -g 2.create-react-app antm-demo 3.cd antm-demo 4.npm start
2. Build the basic development environment of antd mobile
1 - Download
npm install antd-mobile --save
2-src/App.jsx
import React, {Component} from 'react' // Introduce the components to be used separately import Button from 'antd-mobile/lib/button' import Toast from 'antd-mobile/lib/toast' export default class App extends Component { handleClick = () => { Toast.info('Submitted successfully', 2) } render() { return ( <div> <Button type="primary" onClick={this.handleClick}>Submit</Button> </div> ) } }
3- src/index.js
import React from 'react'; import ReactDOM from 'react-dom' import App from "./App" // Introduce overall css import 'antd-mobile/dist/antd-mobile.css' ReactDOM.render(<App />, document.getElementById('root'))
4- index.html
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no" /> <script src="https://as.alipayobjects.com/g/component/fastclick/1.0.6/fastclick.js"></script> <script> if ('addEventListener' in document) { document.addEventListener('DOMContentLoaded', function() { FastClick.attach(document.body); }, false); } if(!window.Promise) { document.writeln('<script src="https://as.alipayobjects.com/g/component/es6-promise/3.2.2/es6-promise.min.js"'+'>'+'<'+'/'+'script>'); } </script>
3. Realize on-demand packaging (component js/css)
1. Download dependent packages
yarn add react-app-rewired --dev yarn add babel-plugin-import --dev
2. Modify the default configuration:
//package.json "scripts": { "start": "react-app-rewired start", "build": "react-app-rewired build", "test": "react-app-rewired test --env=jsdom" } //config-overrides.js const {injectBabelPlugin} = require('react-app-rewired'); module.exports = function override(config, env) { config = injectBabelPlugin(['import', {libraryName: 'antd-mobile', style: 'css'}], config); return config; };
3. Coding
import {Button, Toast} from 'antd-mobile'
13. Redux
13.1 understanding redux
Document link:http://www.redux.org.cn/ :https://www.reduxjs.cn/introduction/getting-started 1.redux It is an independent and specialized tool for state management JS library(no react Plug in Library) 2.It can be used in react, angular, vue Etc, But basically react Use together 3.effect: Centralized management react The state shared by multiple components in the application
When do I need to use redux?
1 General principles: No need if you can, If you don't have to work hard, you can consider using it 2 The state of a component needs to be shared 3 A state needs to be available anywhere 4 A component needs to change the global state 5 One component needs to change the state of another component
redux workflow diagram
13.2 core API of Redux
1.createStore()
effect:
Create a store object containing the specified reducer
code:
import {createStore} from 'redux' import counter from './reducers/counter' const store = createStore(counter)
2.store object
effect:
The core management object of the redux library is internally maintained: state and reducer
Core method:
getState()
dispatch(action)
subscribe(listener)
code:
store.getState() store.dispatch({type:'INCREMENT', number}) store.subscribe(render)
3 . applyMiddleware()
effect:
Middleware based on redux in application (plug-in library)
code:
import {createStore, applyMiddleware} from 'redux' import thunk from 'redux-thunk' // redux asynchronous Middleware const store = createStore( counter, applyMiddleware(thunk) // Asynchronous middleware on Application )
4 . combineReducers()
effect:
Merge multiple reducer functions
code:
export default combineReducers({ user, chatUser, chat })
13.3 three core concepts of Redux
1 . action
1)Identifies the object to perform the behavior 2)Attributes containing 2 aspects a.type: Identity attribute, The value is a string, only, Necessary attributes b.xxx: Data properties, Arbitrary value type, optional attribute 3)example: const action = { type: 'INCREMENT', data: 2 } 4)Action Creator(establish Action Factory function of) const increment = (number) => ({type: 'INCREMENT', data: number})
2 . reducer
1)According to the old state and action, Generate new state Pure function of 2)Example export default function counter(state = 0, action) { switch (action.type) { case 'INCREMENT': return state + action.data case 'DECREMENT': return state - action.data default: return state } } 3)be careful a.Return to a new status b.Do not modify the original state
3 . store
1)take state,action And reducer Linked objects 2)How do I get this object? import {createStore} from 'redux' import reducer from './reducers' const store = createStore(reducer) 3)Functions of this object? getState(): obtain state dispatch(action): distribute action, trigger reducer call, Generate new state subscribe(listener): Register listening, When a new state Time, Automatic call
13.4 writing applications using redux
Download dependent packages
npm install --save redux
redux/action-types.js
/* action Object's type constant name module */ export const INCREMENT = 'increment' export const DECREMENT = 'decrement'
redux/actions.js
/* action creator modular */ import {INCREMENT, DECREMENT} from './action-types' export const increment = number => ({type: INCREMENT, number}) export const decrement = number => ({type: DECREMENT, number})
redux/reducers.js
/* According to the old state and the specified action, the processing returns a new state */ import {INCREMENT, DECREMENT} from '../constants/ActionTypes' import {INCREMENT, DECREMENT} from './action-types' export function counter(state = 0, action) { console.log('counter', state, action) switch (action.type) { case INCREMENT: return state + action.number case DECREMENT: return state - action.number default: return state } }
components/app.jsx
/* Application component */ import React, {Component} from 'react' import PropTypes from 'prop-types' import * as actions from '../redux/actions' export default class App extends Component { static propTypes = { store: PropTypes.object.isRequired, } increment = () => { const number = this.refs.numSelect.value * 1 this.props.store.dispatch(actions.increment(number)) } decrement = () => { const number = this.refs.numSelect.value * 1 this.props.store.dispatch(actions.decrement(number)) } incrementIfOdd = () => { const number = this.refs.numSelect.value * 1 let count = this.props.store.getState() if (count % 2 === 1) { this.props.store.dispatch(actions.increment(number)) } } incrementAsync = () => { const number = this.refs.numSelect.value * 1 setTimeout(() => { this.props.store.dispatch(actions.increment(number)) }, 1000) } render() { return ( <div> <p> click {this.props.store.getState()} times {' '} </p> <select ref="numSelect"> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> </select>{' '} <button onClick={this.increment}>+</button> {' '} <button onClick={this.decrement}>-</button> {' '} <button onClick={this.incrementIfOdd}>increment if odd</button> {' '} <button onClick={this.incrementAsync}>increment async</button> </div> ) } }
index.js
import React from 'react' import ReactDOM from 'react-dom' import {createStore} from 'redux' import App from './components/app' import {counter} from './redux/reducers' // Create a store object according to the counter function const store = createStore(counter) // Defines the function that renders the root component label const render = () => { ReactDOM.render( <App store={store}/>, document.getElementById('root') ) } // Initialize rendering render() // Register (subscribe) to listen. Once the state changes, it will automatically re render store.subscribe(render)
problem
1)redux And react The code coupling of the component is too high 2)The coding is not concise enough
13.5 react-redux
understand
1) A react plug-in library
2) Designed to simplify the use of redux in react applications
React Redux divides all components into two categories
1)UI components
a.Only responsible UI Without any business logic b.adopt props receive data (General data and functions) c.Do not use any Redux of API d.Generally stored in components Under folder
2) Container assembly
a.Responsible for managing data and business logic, not UI Presentation of b.use Redux of API c.Generally stored in containers Under folder
Related API
1)Provider
Make state data available to all components
<Provider store={store}> <App /> </Provider>
2)connect()
Container component used to wrap UI components
import { connect } from 'react-redux' connect( mapStateToprops, mapDispatchToProps )(Counter)
3)mapStateToprops()
Convert external data (i.e. state object) into tag properties of UI components
const mapStateToprops = function (state) { return { value: state } }
4)mapDispatchToProps()
Convert the function that distributes the action into the tag attribute of the UI component
Concise syntax can be directly specified as actions objects or objects containing multiple action methods
Using react Redux
1) Download dependent packages
npm install --save react-redux
2)redux/action-types.js
unchanged
3)redux/actions.js
unchanged
4)redux/reducers.js
unchanged
5)components/counter.jsx
/* UI Component: does not contain any redux API */ import React from 'react' import PropTypes from 'prop-types' export default class Counter extends React.Component { static propTypes = { count: PropTypes.number.isRequired, increment: PropTypes.func.isRequired, decrement: PropTypes.func.isRequired } increment = () => { const number = this.refs.numSelect.value * 1 this.props.increment(number) } decrement = () => { const number = this.refs.numSelect.value * 1 this.props.decrement(number) } incrementIfOdd = () => { const number = this.refs.numSelect.value * 1 let count = this.props.count if (count % 2 === 1) { this.props.increment(number) } } incrementAsync = () => { const number = this.refs.numSelect.value * 1 setTimeout(() => { this.props.increment(number) }, 1000) } render() { return ( <div> <p> click {this.props.count} times {' '} </p> <select ref="numSelect"> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> </select>{' '} <button onClick={this.increment}>+</button> {' '} <button onClick={this.decrement}>-</button> {' '} <button onClick={this.incrementIfOdd}>increment if odd</button> {' '} <button onClick={this.incrementAsync}>increment async</button> </div> ) } }
6)containters/app.jsx
/* Container component containing Counter component */ import React from 'react' // Introduce connection function import {connect} from 'react-redux' // Introduce action function import {increment, decrement} from '../redux/actions' import Counter from '../components/counter' // Expose packaging components connecting App components to the outside export default connect( state => ({count: state}), {increment, decrement} )(Counter)
7)index.js
import React from 'react' import ReactDOM from 'react-dom' import {createStore} from 'redux' import {Provider} from 'react-redux' import App from './containers/app' import {counter} from './redux/reducers' // Create a store object according to the counter function const store = createStore(counter) // Defines the function that renders the root component label ReactDOM.render( ( <Provider store={store}> <App /> </Provider> ), document.getElementById('root')
problem
1)redux Asynchronous processing is not allowed by default, 2)In the application, we need to redux Executing asynchronous tasks in(ajax, timer)
13.6 redux asynchronous programming
Download redux plug-in (asynchronous Middleware)
npm install --save redux-thunk
index.js
import {createStore, applyMiddleware} from 'redux' import thunk from 'redux-thunk' // Create a store object according to the counter function const store = createStore( counter, applyMiddleware(thunk) // Asynchronous middleware on Application )
redux/actions.js
// Asynchronous action creator (return a function) export const incrementAsync = number => { return dispatch => { setTimeout(() => { dispatch(increment(number)) }, 1000) } }
components/counter.jsx
incrementAsync = () => { const number = this.refs.numSelect.value*1 this.props.incrementAsync(number) }
containers/app.jsx
import {increment, decrement, incrementAsync} from '../redux/actions' // Expose packaging components connecting App components to the outside export default connect( state => ({count: state}), {increment, decrement, incrementAsync} )(Counter)
13.7 using redux debugging tool
Install the chrome browser plug-in
Download and decompress, and directly drag it into the extension program interface
Download tool dependency package
npm install --save-dev redux-devtools-extension
code
import { composeWithDevTools } from 'redux-devtools-extension' const store = createStore( counter, composeWithDevTools(applyMiddleware(thunk)) )
13.8 relevant important knowledge: pure function and higher-order function
1. Pure function
1.1 a special kind of function: as long as it is the same input, it must get the same output
1.2 some of the following constraints must be observed
a. Parameters must not be overwritten
b. API of system I/O cannot be called
c. Can call date Now () or math Impure methods such as random ()
1.3 the reducer function must be a pure function
2. Higher order function
2.1 understanding: a special class of functions
a. Case 1: the parameter is a function
b. Case 2: return is a function
2.2 common high-order functions:
a. Timer setting function
b. map()/filter()/reduce()/find()/bind() of array
c. connect function in react Redux
2.3 function: it can realize more dynamic and scalable functions