I learned React a couple of days ago, especially record the learning process, React novice where can optimize the message to the big guy advice, little brother extremely thanks!

Project initialization

React Scaffolding

    create-react-app react-shop-dome
Copy the code

Delete more files SRC leave app.js and index.js and delete the corresponding ones

2. Introduce ANTD and ANTD-Mobile

1. Download the dependency package

npm install antd antd-mobile -S
Copy the code

2. Load on demand

npm install babel-plugin-import react-app-rewired customize-cra --dev
Copy the code

Modify the package. The json

"scripts": {
-   "start": "react-scripts start",
+   "start": "react-app-rewired start",
-   "build": "react-scripts build",
+   "build": "react-app-rewired build",
-   "test": "react-scripts test",
+   "test": "react-app-rewired test",
}
Copy the code

Create a config-overrides. Js file in the root directory of the project to modify the default configuration

Const {override, fixBabelImports} = require('customize-cra'); module.exports = override( fixBabelImports('pc', { libraryName: 'antd', libraryDirectory: 'es', style: 'css', }), fixBabelImports('mobile', { libraryName: 'antd-mobile', libraryDirectory: 'es', style: 'css', }), );Copy the code

3. Customize themes

npm install less less-loader -D
Copy the code

Then modify the config-overrides. Js configuration

const { override, fixBabelImports, addWebpackAlias, addLessLoader } = require('customize-cra'); const path = require("path"); Module. exports = override(// implement antd /ant-mobile on demand import fixBabelImports(' PC ', {libraryName: 'antd', libraryDirectory: 'es', // style: 'CSS ', style: true, // theme to take effect}), // fixBabelImports('mobile', {// libraryName: 'antd-mobile', // libraryDirectory: 'es', // style: 'css', // }), addLessLoader({ javascriptEnabled: true, modifyVars: {' @ primary - color: '# 1 da57a},}), / / alias configuration addWebpackAlias ({[" @ "] : path. Resolve (__dirname, ". / SRC "), [] "@ v" : path.resolve(__dirname, "./src/views"), ["@c"]: path.resolve(__dirname, "./src/components") }) );Copy the code

4. Configure routes

App.js

import React from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import { Provider } from 'react-redux';
import Admin from '@v/Admin'
import Login from '@v/Login';
import './assets/style/base.less'
function App() {
  return (
    <Router>
      <Switch>
        <Route path='/' exact component={Admin}></Route>
        <Route path='/login' component={Login}></Route>
      </Switch>
    </Router>
  );
}

export default App;
Copy the code

5. Login page

import React, { Component } from 'react' import { Form, Input, Button, Checkbox } from 'antd'; import { UserOutlined, LockOutlined } from '@ant-design/icons'; import './login.less' import api from '.. /.. / API /index.js' export default class Login extends Component {// onFinish = values => { Console. log(' Get form data: ', values); api.login({ "username": "admin", "password": "123456" }).then(res => { console.log(res); / / jump to the administrative interface Do not need to be back with the replace this. Props. The history, the replace ('/')})}; Render () {return (<div className="login"> <header className='login-header'><h2>React project - admin </h2></header> <section ClassName ='login-content'> <h3> User login </h3> <Form name="normal_login" className="login-form" // Form default value initialValues={{ remember: true, username:'admin', password:'123456', }} onFinish={this.onFinish} > < form. Item name="username" validateFirst='true' rules={[{// required: Whitespace: true, message: 'Please enter username ',}, {min: 4, message:' username minimum 4 digits ',}, {Max: 12, message: 'user name up to 12'}, {pattern: / ^ / a - zA - Z0-9 _ + $/, the message: 'Username must consist of English, numbers or underscores ',}, ]} > <Input prefix={< statements className="site form-item-icon" />} placeholder=" user name "/> </ form.item > < form.item name="password" rules={[ { required: true, whitespace: true, message: 'Please enter password ',}, ]} > <Input prefix={(bank statements) bank statements =" bank statements "/> </ outline > < form. Item> < form. Item name="remember" valuePropName="checked" noStyle> <Checkbox> Remember password </Checkbox> </ form. Item> </ form. Item> <Form.Item> <Form type="primary" htmlType="submit" className="login-form-button"> </Form.Item> </Form> </section> </div> ) } }Copy the code

6. Send the request (Axios)

2. API create request.js and index.jsCopy the code

request.js

import axios from 'axios'; import { message } from 'antd'; const $axios = axios.create({ // baseURL: process.env.xxxx, timeout: 6000, retry: 4, retryDelay: 1000 }); / / request intercept $axios. Interceptors. Request. Use (config = > {/ / do something before sending a request / / by reudx store to get a global state tree token, added to the request message, The background will return to the status according to the newspaper article / / here should be based on specific business writing token / / const token = store. The getState (). The user. The token | | localStorage. The getItem (" token "); const token = 'FA2019'; config.headers['X-Token'] = token; console.log(config) return config; }, error => {// Do something about the request error message.error(error); return Promise.reject(error); }); / / add the response interceptor $axios. Interceptors. Response. Use (response = > {return Promise. Resolve (response)}, Error => {console.log(error. Response) // for debug // Processing the HTTP status code of the request failed message.error(' request failed '); return Promise.reject(error) } ); Export default function request(URL, data = {}, method = 'POST') {return new Promise((resolve, resolve) reject) => { const options = method === 'POST' ? { url, method, data } : { url, method, params: data } $axios(options) .then(res => { const {data}= {... Res} console.log(' return data ', res) if (data.code! == 0) { message.error(data.msg); } else { resolve(data.data) } }) .catch(error => { reject() console.error(error) }) }) }Copy the code

index.js

Import request from './request' const API = {// Login (data) {return request('/admin/login/login', data) } } export default apiCopy the code

7. Use redux

npm i redux -S
Copy the code

Story ideas

Create store -> inject store into application -> component get state data in store

1. Create the store

1. The createStore method needs to be imported from redux to create a Store object. 2. Because createStore needs to pass parameters: reducers and middleware (aside for now), you need to create the reducers function 3. Create the reducers function, which takes two parameters: state and Action. This function must return a new state 4. Will create successful reducers function into createStore method -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- The SRC /store/index.js // applyMiddleware method is used to import {createStore, ApplyMiddleware} from 'redux' import rootReducer from './reducers createStore(rootReducer) export default store ------------------------------------------------------------------ SRC/store/reducers/index. Js / / introduce combineReducers method, Use to merge multiple reducers into a rootReducer import {combineReducers} from 'redux' import {userReducer} from './userReducer' let rootReducer = combineReducers({ userModule: userReducer }) export default rootReducer ----------------------------------------------------------------------- src/store/reducers/userReducer.js let initState = { loginState: } export const userReducer = (state = initState, action) => { switch (action.type) { case 'CHANGE_LOGIN_STATE': return {... state, loginState: action.payload} default: return state } }Copy the code

React and Redux connect

index.js

import React from 'react'; import ReactDOM from 'react-dom'; Store import {Provider} from 'react-redux' import store from './store' import App from ' './App'; ReactDOM.render(<Provider store={store}> <App />Copy the code

How do other components call state in redux or trigger the Reducer function

import {connect} from "react-redux"; // Before using connect(), Const mapStateToProps = (state) => {return {const mapStateToProps = (state) => {return { user: state.userModule }; }; In addition to reading state, container components can also distribute actions. In a similar way, Const mapDispatchToProps = (dispatch) => {return can be defined to receive the Dispatch () method and return the callback method expected to be injected into the props of the presentation component  { setName: (name) => { dispatch({ type: "SET_NAME", payload: name }); }}; }; export default connect(mapStateToProps, mapDispatchToProps)(App); // A reducer can be triggered with this.props. EtName (' XXX ')Copy the code

8. Route authentication

Create AuthRouter high-order component in Component

Import React from 'React' import {withRouter} from 'react-router'; import { Route, Redirect } from 'react-router-dom'; import { connect } from 'react-redux' const AuthRouter = ({ component: Component, ... rest }) => { // console.log(rest); const isLogged = rest.loginState; return <Route {... rest} render={props => (isLogged ? <Component {... props} /> : <Redirect to={'/login'} />)} />; }; Const mapStateToProps = (state) => {return {loginState: const mapStateToProps = (state) => {return {loginState: state.userModule.loginState } } export default connect(mapStateToProps)(withRouter(AuthRouter)) // export default connect(mapStateToProps)(AuthRouter)Copy the code

Create the Routers file in SRC to manage routes and import AuthRouter

import React from 'react';
import { HashRouter, Route, Switch } from 'react-router-dom';
import Login from '@/views/Login';
import Layout from '@/views/Layout';
import AuthRouter from '@c/AuthRouter';
const Router = () => {
	return (
		<HashRouter>
			<Switch>
				<Route component={Login} exact path="/login" />
				<AuthRouter path="/" component={Layout} />
			</Switch>
		</HashRouter>
	);
};

export default Router;
Copy the code

Modify the App. Js

import React from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import Admin from '@v/Admin'
import Login from '@v/Login'
import AuthRouter from '@c/AuthRouter';
import './assets/style/base.less'
function App() {
  return (
    <Router>
      <Switch>
        <Route path='/login' component={Login}></Route>
        <AuthRouter path='/' component={Admin}></AuthRouter>
      </Switch>
    </Router>
  );
}

export default App;
Copy the code

Successful login On the login page Modify the login status in the userReducer user module in Redux by sending action

The Login. Js modified to

import React, { Component } from 'react' import { connect } from 'react-redux' import { Form, Input, Button, Checkbox,message } from 'antd'; import { UserOutlined, LockOutlined } from '@ant-design/icons'; import './login.less' import api from '.. /.. / API /index.js' class Login extends Component {onFinish = values => {console.log(' Get form data: ', values); api.login({ "username": values.username, "password": values.password }).then(res => { console.log(res); Message. Success (' login successfully, 2), then (() = > {/ / modify login state this. Props. ChangeLoginState (true) / / jump to the corresponding page do not need to be back with the replace let {from}  = this.props.location.state || { from: { pathname: "/" } } this.props.history.replace(from.pathname) }); })}; Render () {return (<div className="login"> <header className='login-header'><h2>React project - admin </h2></header> <section ClassName ='login-content'> <h3> User login </h3> <Form name="normal_login" className="login-form" // Form default value initialValues={{ remember: true, username: 'admin', password: '123456',}} onFinish={this.onFinish} > < form. Item name="username" validateFirst='true' rules={[{// Required: Whitespace: true, message: 'Please enter username ',}, {min: 4, message:' username minimum 4 digits ',}, {Max: 12, message: 'user name up to 12'}, {pattern: / ^ / a - zA - Z0-9 _ + $/, the message: 'Username must consist of English, numbers or underscores ',}, ]} > <Input prefix={< statements className="site form-item-icon" />} placeholder=" user name "/> </ form.item > < form.item name="password" rules={[ { required: true, whitespace: true, message: 'Please enter password ',}, ]} > <Input prefix={(bank statements) bank statements =" bank statements "/> </ outline > < form. Item> < form. Item name="remember" valuePropName="checked" noStyle> <Checkbox> Remember password </Checkbox> </ form. Item> </ form. Item> <Form.Item> <Form type="primary" htmlType="submit" className="login-form-button"> < / Form Item > < / Form > < section > < / div >)}} / / create a mapping function, Submit Action const mapActionToProps = (dispatch) => {return {changeLoginState: (newState) => {dispatch({type: 'CHANGE_LOGIN_STATE', payload: newState }) } } } export default connect(null, mapActionToProps)(Login)Copy the code

9, Redux persistence (sessionStorage implementation)

App.js adds pre-refresh events to save redux data locally

import React from 'react'; import { BrowserRouter as Router, Route, Switch, Redirect } from 'react-router-dom'; import { connect } from 'react-redux' import Admin from '@v/Admin' import Login from '@v/Login' import AuthRouter from '@c/AuthRouter'; import './assets/style/base.less' function App(props) { window.onbeforeunload = (e) => { console.log(props); sessionStorage.setItem('store', JSON.stringify(props.state)); }; return ( <Router> <Switch> <Route path='/login' component={Login}></Route> <AuthRouter path='/' component={Admin}></AuthRouter> <Redirect to="/404" /> </Switch> </Router> ); } const mapStateToProps = (state) => {console.log(state); return { state } } // export default App; export default connect(mapStateToProps)(App)Copy the code

Add locally stored data to the createStore function when creating a Store instance

The applyMiddleware method is used to use middleware import {createStore, applyMiddleware } from 'redux' import rootReducer from './reducers' const initialState = sessionStorage.getItem('store') ? JSON.parse(sessionStorage.getItem('store')) : {} console.log(initialState); Let store = createStore(rootReducer, initialState) sessionStorage.removeItem('store') export default storeCopy the code

To the completion of the previous two days of learning, in the future will continue to improve the application of other functions source address: github.com/panzekun/re…