Note source: Hook Education – big front end employment Training camp

Content: Notes, thoughts and experiences in the process of learning

Tip: project actual combat article resources can not be uploaded, only for reference

Pull hook education books e-commerce project actual combat – on

Introduction to technology Stack

Page layout useAnt DesignThe component library performs operations

The client

  • Front-end framework: React
  • Route management: react-router-dom
  • User Interface: ANTD (UI Component Library)
  • Global state management: REdux
  • Asynchronous status updates: redux-saga
  • Network request: Axios
  • Status debugging tool: redux-devtools-extension

The service side

  • Script: node. Js
  • Database: mongodb
  • Database visualization: mongodb-Compass

Setting up the development Environment (server)

Installing the mongodb Database (on a Mac Terminal)

  1. Install Homebrew (Software Package Manager for MAC)

    // There is a problem with the method provided by the teacher, you can use this command to install, select 1 - USTC source
    /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)"
    
    // After the installation, you can enter the following command to check whether the installation is successfulBrew or BREW-VCopy the code
  2. Add the mongodb repository source

    // May need to climb the wall, I did it for a long time
    brew tap mongodb/brew
    Copy the code
  3. Install the mongo

    // Run the command to install
    brew install mongodb-community
    
    // Verify the installation
    mongod --version
    Copy the code

    If an error message is displayed indicating that Xcode is not installed, install Xcode

    / / xcode installation
    xcode-select --install
    Copy the code
  4. Start the mongo

    / / start
    brew services run mongodb-community
    
    - Successfully ran 'mongodb-community'.... Indicates successful startup.
    Copy the code
  5. Stop the mongo

    / / stop
    brew services stop mongodb-community
    
    -stopping 'mongodb-community' // If the console does not return an error, the system will be stopped successfully.
    Copy the code
  6. File location (generally not adjusted)

    • 1. Database configuration file/usr/oca/etc/mongod.conf
    • 2. The default location for storing database files is:/usr/local/var/mongodb
    • 3. Log storage location:/usr/ocal/var/log/mongodb/mongo.log

Installing the mongodb Database on Windows

You don’t have a Windows device, so go online and find a tutorial. Just install a software and you may need to set environment variables

Install the mongodb visualization softwareRobo 3T

Setting up the development environment

Create project installation dependencies

  1. Create projects using scaffolding: NPM install -g [email protected]

  2. Create project: NPM init React-app project name, use lagou-carefully selected in the course

  3. Installation project dependencies

    NPM install [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected]

    + moment@2.291.
    + axios@0.211.
    + redux@4.0. 5
    + redux-saga@1.13.
    + redux-devtools-extension@2.139.
    + react-redux@7.22.
    + react-router-dom@5.2. 0
    + antd@4.14. 0   // Ant Design - UI component library
    Copy the code
  4. Clean up unnecessary files, directories, and code in your project

  5. Antd CSS uses CDN, version 4.14.0 for teachers. Copy this tag to the head of the HTML template file public/index.html

    < link rel = "stylesheet" href = "https://cdnjs.cloudflare.com/ajax/libs/antd/4.14.0/antd.min.css" / >

Switch server request addresses based on the development environment

In the development environment and production environment, different interface addresses need to be used. This step does not need to be manually modified, and the program can automatically switch the interface address according to the environment

  1. Configure and use environment variables in code using the create-React-app built-in Dotenv

    // Create a file with the directory -.env
    // Address of the production (online) environment interface
    REACT_APP_PRODUCTION_API_URL=http://fullstack.net.cn/api
    // Address of the development environment interface
    REACT_APP_DEVLOPMENT_API_URL=http://localhost/api
    
    / / note:
    // 1. The environment variable name must start with REACT_APP_
    // 2, don't write on one line, don't ask why
    Copy the code
  2. Write the request address to the configuration and decide which API address to use depending on the environment

    // SRC /config.js creates a configuration file that uses different addresses depending on the environment
    
    // Create a variable to represent the request address. By default, use the development environment address
    export let API = process.env.REACT_APP_DEVLOPMENT_API_URL
    
    // Check whether the system is in production
    if (process.env.NODE_ENV === "production") {
      // Change the IP address to the IP address of the production environment
      API = process.env.REACT_APP_PRODUCTION_API_URL
    }
    Copy the code

In a project, you can access it through process.env.react APPDEVLOPMENTAPIURL, but this has disadvantages. First, the code is too long to write easily, and second, if the environment is dead in the code, it is not easy to change when switching environments. The solution is to write the AP address into the configuration and decide which AP address to use based on the environment

Install browser extensions

  • React Developer Tools Displays the React component hierarchy and props information

    • Click on the Components TAB in Developer mode
  • Redux Devtools: Monitors state changes in the Store

    • Click on the Redux TAB in Developer mode

    • Configuration is required to use Redux Devtools

      // Introduce composeWithDevTools wrapped middleware to make use of the Redux Devtools plugin functionality
      import { composeWithDevTools } from 'redux-devtools-extension'
      
      export constStore = createStore(data,// Wrap the middleware with methods
        composeWithDevTools(applyMiddleware(...))
      )
      Copy the code

Create a project Layout and route

Rfce can quickly create components installed plugin (I), ES7 React/story/GraphQL/React – Native snippets plug-in can quickly create structure, reference

  • SRC directory creates the Components directory to prevent all Components, containing two directories:
    • Admin directory: Places components related to the background management page (accessible only to administrators)
    • Core directory: To place foreground page-related components (regular user access)
      • Layout components: Each page component has a common structure, with other components as children of the common component
      • Home component: Home page
      • Shop component: Item list component
    • Routes component: A routing rule component used in index.js instead of the App component as the root component
/ / SRC/Components/core/Home. Js page Components

import React from 'react'
// Introduce common components
import Layout from './Layout'

function Home() {
  return (
    // The outermost layer is the public component, which is a child of the public component
    <Layout>Home page</Layout>)}export default Home

Copy the code
/ / SRC/Components/core/Shop. Js commodity list component

import React from 'react'
// Introduce common components
import Layout from './Layout'

function Shop() {
  return (
    // The outermost layer is the public component, which is a child of the public component
    <Layout>List of goods</Layout>)}export default Shop

Copy the code
// SRC /Components/ routes.js

import React from 'react'
BrowserRouter is similar to HashRouter and is more recommended
import { Switch, BrowserRouter, Route } from 'react-router-dom'
// Import the routing component
import Home from './core/Home'
import Shop from './core/Shop'

function Routes() {
  return (
    // Enable the routing function for the package
    <BrowserRouter>{/* Avoid writing errors in the same route */}<Switch>{/* Route, the first route is the default route, exact match */}<Route path="/" component={Home} exact />
        <Route path="/shop" component={Shop} />
      </Switch>
    </BrowserRouter>)}export default Routes

Copy the code
// SRC /index.js replaces the default App component with a routing component

import React from 'react'
import ReactDOM from 'react-dom'
// Import the routing component
import Routes from './Components/Routes'


ReactDOM.render(
  <React.StrictMode>{/* Replace APP with routing component */}<Routes />
  </React.StrictMode>.document.getElementById('root'))Copy the code
/ / SRC/Components/core/Layout. Js common Components

import React from 'react'

// Public component, deconstruct the child component content
// Children is the content passed by the child component
function Layout({children}) {
  console.log(children)
  return (
    <div>{/* Write public component content */} public component content {/* Use child component content directly */} {children}</div>)}export default Layout

Copy the code

Global Store initialization

  • Create a Store directory in the SRC directory
    • Create index.js file: Create store, export store
    • Create the Reducers directory: Store and export the reducers
      • Create the index.js file, merge all the reducers and export it
      • Create the test.js file with a reducer

Create a reducer – Merge all the reducer – Create a store using the reducer – Pass the store to the root component Enable the repository – Obtain the state using the component (test)

/ / SRC/store/reducers/text, js, create a reducer for storing state data

Create a reducer and export it
export default function testReducer(state = 0) {
  return state
}

Copy the code
/ / SRC/store/reducers/index, js incorporating all reducer for export

// Import the reducer merge method
import { combineReducers } from "redux";
// Import the reducer to merge
import testReducer from "./text";

/ / merge
const rootReducer = combineReducers({
  test: testReducer
})

/ / export
export default rootReducer
Copy the code
// SRC /store/index.js Create the repository using the reducer merged above

// Create store method
import { createStore } from "redux";
Reducer to use
import rootReducer from "./reducers";

// Create store repository
const store = createStore(rootReducer)

export default store
Copy the code
// SRC /index.js formally passes and enables the repository

import React from 'react'
import ReactDOM from 'react-dom'
// Import the routing component
import Routes from './Components/Routes'
// Introduce methods to pass the store repository
import { Provider } from 'react-redux'
/ / into the store
import store from './store'


ReactDOM.render(
  <React.StrictMode>{/* Pass on the store repository to enable */}<Provider store={store}>{/* Replace APP with routing component */}<Routes />
    </Provider>
  </React.StrictMode>.document.getElementById('root'))Copy the code
/ / SRC/Components/core/Home. Js Components from the data obtained from the store

import React from 'react'
// Introduce common components
import Layout from './Layout'
// Introduce the getstate method
import {useSelector} from 'react-redux'

function Home() {
  // Create a variable to retrieve the state from Redux's store (state)
  const state = useSelector(state= > state)
  // Print it
  console.log(state)
  return (
    // The outermost layer is the public component, which is a child of the public component
    <Layout>Home page content</Layout>)}export default Home

Copy the code

Route status is synchronized to the global Store

Synchronize routing information to the global Store so that both page components and non-page components can get it

useconnected-react-routerThird-party packages

Using the step

  1. Merge the Reducer code and add a new attribute

  2. Add the routing middleware when creating the store, where the history is retrieved and used

  3. Tweak the logic for shipping and enabling the warehouse

    So this is a little bit of a hassle, so I’m just going to write it fixed, and then I’m just going to copy it

// src/store/reducers/index.js

// Introduce the module method
import { connectRouter } from "connected-react-router";
// Import the reducer merge method
import { combineReducers } from "redux";
// Import the reducer to merge
import testReducer from "./text";

// Merge all reducer
// createRootReducer is a function, do not change the name
const createRootReducer = history= > combineReducers({
  test: testReducer,
  // Routing information
  router: connectRouter(history)
})

/ / export
export default createRootReducer
Copy the code
// src/store/index.js

// Create store method
import { createStore, applyMiddleware } from "redux";
Reducer to use
import createRootReducer from "./reducers";
import { createBrowserHistory } from 'history'
import { routerMiddleware } from 'connected-react-router'

/ / export history
export const history = createBrowserHistory()

// Create store repository
const store = createStore(
  createRootReducer(history),
  // The middleware monitors route changes
  applyMiddleware(routerMiddleware(history))
)

export default store
Copy the code
// src/index.js

import React from 'react'
import ReactDOM from 'react-dom'
// Import the routing component
import Routes from './Components/Routes'
// Introduce methods to pass the store repository
import { Provider } from 'react-redux'
/ / into the store
import store, { history }  from './store'
import { ConnectedRouter } from 'connected-react-router'


ReactDOM.render(
  <React.StrictMode>{/* Pass on the store repository to enable */}<Provider store={store}>{/* Wrapper implementation monitors route changes */}<ConnectedRouter history={history}>{/* Replace APP with routing component */}<Routes />
      </ConnectedRouter>
    </Provider>
  </React.StrictMode>.document.getElementById('root'))Copy the code
// SRC /Components/ routes.js delete the 
      
        of the outer package
      

import React from 'react'
BrowserRouter is similar to HashRouter and is more recommended
import { Switch, BrowserRouter, Route } from 'react-router-dom'
// Import the routing component
import Home from './core/Home'
import Shop from './core/Shop'

function Routes() {
  return (
    // Enable the routing function for the package.
      // {/* Avoid writing errors in the same route */}
      <Switch>{/* Route, the first route is the default route, exact match */}<Route path="/" component={Home} exact />
        <Route path="/shop" component={Shop} />
      </Switch>)}export default Routes

Copy the code

Create navigation menu

  • Create a navigation component as the navigation menu component and add this component to the public component.
  • Using the Ant Design component’s navigation menu, if you find that there is no style, you may not have imported the antD style file.
  • Set navigation to landscape display (default landscape)
  • Enable enable select, that is, click the navigation to display the selected effect. Enable select requires routing information
/ / SRC/Components/core/Navgation js top navigation component

import React from 'react'
// Import the navigation component
import { Menu } from 'antd'
// Introduce a method to get stre status
import { useSelector} from 'react-redux'
// Introduce a jump route method
import { Link } from 'react-router-dom'

// Top navigation component
function Navgation() {
  // Get the status - routing information
  const state = useSelector(state= > state.router)
  return (
    <div>{/* Use navigation component, mode - Landscape, selectedKeys - Set selected (array uses current routing information) */}<Menu mode='horizontal' selectedKeys={[state.location.pathname]}>{/* key corresponds to the above selectedKeys */}<Menu.Item key='/'>{/* Set click jump route */}<Link to='/'>Home page</Link>
        </Menu.Item>
        <Menu.Item key='/shop'>
          <Link to='/shop'>List of goods</Link>
        </Menu.Item>
        <Menu.Item key='/logIn'>
          <Link to='/logIn'>The login</Link>
        </Menu.Item>
        <Menu.Item key='/logUp'>
          <Link to='/logUp'>registered</Link>
        </Menu.Item>
      </Menu>
    </div>)}export default Navgation
Copy the code
/ / SRC/Components/core/Layout. Js Layout container to add common Components

import React from 'react'
// Introduce common enablers
import Navgation from './Navgation'

// The common component (layout) container deconstructs the child component content, and children are the content passed by the child component
function Layout({children}) {
  return (
    <div>{/* Public components */}<Navgation />{/* Use child component content directly */} {children}</div>)}export default Layout
Copy the code

Create a header

Use header components

The same is true for every page, so put it in the Layout common component

Each page is presented with a title and subtitle that are passed to the Layout component to display

You can use the CSS file provided by the teacher to adjust the style by setting the header class name

/ / SRC/Components/core/Layout. Add header js

import React from 'react'
// Introduce common enablers
import Navgation from './Navgation'
// Introduce the UI component - header
import { PageHeader } from 'antd'
// Introduce CSS styles
import '.. /.. /style.css'

// The common component (layout) container deconstructs the child component content, and children are the content passed by the child component
// title, subTitle is passed by other page components
function Layout({children, title, subTitle}) {
  return (
    <div>{/* Public components */}<Navgation />{/* header, set the class name, use title and subTitle */}<PageHeader className="jumbotron" title={title} subTitle={subTitle} />{/* Use child component content directly */} {children}</div>)}export default Layout
Copy the code
/ / SRC/Components/core/Home. Js transmission header you need to use the text

import React from 'react'
// Introduce common components
import Layout from './Layout'
// Introduce the getstate method
// import {useSelector} from 'react-redux'

function Home() {
  // Create a variable to retrieve the state from Redux's store (state)
  // const state = useSelector(state => state)
  return (
    // The outermost layer is the public component, which is a child of the public component
    // Pass title, subTitle
    <Layout title='home' subTitle='Start your shopping trip.'>Home page content</Layout>)}export default Home
Copy the code
/ / SRC/Components/core/Shop. Js transmission header you need to use the text

import React from 'react'
// Introduce common components
import Layout from './Layout'

function Shop() {
  return (
    // The outermost layer is the public component, which is a child of the public component
    // Pass title, subTitle
    <Layout  title='List of Goods' subTitle='Start shopping'>List of goods</Layout>)}export default Shop
Copy the code

Build the registration and login forms

Core directory creates both login and registration components

Login and registration also require the use of the common component Layout, again passing in the header information

Add the routing rules for the two new pages to the routing rule component

The navigation menu also needs to add navigation for the two components (already added)

Both login and registration are built using the From form component

After writing, I found that it is not centered on the page, because every page should be centered on the page, so I set the page content center in Layout

/ / SRC/Components/core/Login. The Login js new Components

import React from 'react'
// Introduce a common layout container
import Layout from './Layout'
// Import UI components
import { Form, Input, Button } from 'antd'

// Login component
function Login() {
  return (
    // Export the layout container, passing title and subTitle
    <Layout  title='login' subTitle='Please log in to your account'>{/ * * /} forms<Form>
        <Form.Item
          label="E-mail"
          name="email"/ / checkrules={[{ required: true.message:'Please enter email! '}}] >
          <Input />
        </Form.Item>
        <Form.Item
          label="Login password"
          name="password"
          rules={[{ required: true.message:'Please enter your password! '}}] >
          <Input.Password />
        </Form.Item>
        <Form.Item wrapperCol={{ offset: 8.span: 16}} >
          <Button type="primary" htmlType="submit">The login</Button>
        </Form.Item>
      </Form>
    </Layout>)}export default Login
Copy the code
/ / SRC/Components/core/Logup js new registered Components

import React from 'react'
// Import the layout container
import Layout from './Layout'
// Import the UI component
import { Form, Input, Button } from 'antd'

// Register the component
function Logup() {
  return (
    // Export the layout container, passing title and subTitle
    <Layout  title='registered' subTitle='Set up an account.'>{/ * * /} forms<Form>
        <Form.Item
          label="Login nickname"
          name="name"/ / checkrules={[{ required: true.message:'Please enter a user name! '}}] >
          <Input />
        </Form.Item>
        <Form.Item
          label='Login password'
          name="password"
          rules={[{ required: true.message:'Please enter your password! '}}] >
          <Input.Password />
        </Form.Item>
        <Form.Item
          label="E-mail"
          name="email"
          rules={[{ required: true.message:'Please enter email! '}}] >
          <Input />
        </Form.Item>
        <Form.Item wrapperCol={{ offset: 8.span: 16}} >
          <Button type="primary" htmlType="submit">registered</Button>
        </Form.Item>
      </Form>
    </Layout>)}export default Logup
Copy the code
// SRC /Components/ routes.js Add two Routes for login and registration

import React from 'react'
BrowserRouter is similar to HashRouter and is more recommended
import { Switch, Route } from 'react-router-dom'
// Import the routing component
import Home from './core/Home'
import Login from './core/Login'
import Logup from './core/Logup'
import Shop from './core/Shop'

function Routes() {
  return (
    // Enable the routing function for the package.
      // {/* Avoid writing errors in the same route */}
      <Switch>{/* Route, the first route is the default route, exact match */}<Route path="/" component={Home} exact />
        <Route path="/shop" component={Shop} />
        <Route path="/login" component={Login} />
        <Route path="/logup" component={Logup} />
      </Switch>)}export default Routes
Copy the code
/ / SRC/Components/core/Layout. Js Layout container set left and right margins as a whole

import React from 'react'
// Introduce common enablers
import Navgation from './Navgation'
// Introduce the UI component - header
import { PageHeader } from 'antd'
// Introduce CSS styles
import '.. /.. /style.css'

// The common component (layout) container deconstructs the child component content, and children are the content passed by the child component
// title, subTitle is passed by other page components
function Layout({children, title, subTitle}) {
  return (
    <div>{/* Public components */}<Navgation />{/* header, set the class name, use title and subTitle */}<PageHeader className="jumbotron" title={title} subTitle={subTitle} />{/* Directly use the child component content, set the two margins */}<div style={{width: '85% ',margin: '0 auto'}} >{children}</div>
    </div>)}export default Layout
Copy the code

Implement a registered Redux workflow

Create action and React

Install [email protected] simplified code – NPM I [email protected]

Create an Actions directory in the store directory to hold action directives

Create a separate file in the Actions directory to write the registration instructions

Create four commands (cerateAction) : initiate registration request, register success, register failure, reset registration status (used when leaving registration status)

Create a Reducer for registration in the reducers directory

Create registration related status data {whether the request was being sent, whether the request was completed, whether the request was successful, and why the request failed}

Merge the registered related reducer

/ / SRC/store/actions/logup action. Js file writing new registration related instructions

// Introduce methods to simplify Redex writing
import { createAction } from 'redux-actions'

// Four commands
// Initiate a registration request
export const logup = createAction('logup')
// Registration succeeded
export const logup_success = createAction('logup_success')
// Failed to register
export const logup_fail = createAction('logup_fail')
// Reset the registration state (restore the registration state when leaving the registration page)
export const logup_reset = createAction('logup_reset')
Copy the code
/ / SRC/store/reducers/logup reducer. The state of js file written registration related new reducer

// Introduce methods to simplify Redux
import { handleActions } from 'redux-actions'
// Import the required instructions
import { logup, logup_fail, logup_reset, logup_success } from '.. /actions/logup.action'

// Create the registered component state
const logupDate = {
  loadering: false.// Whether a request is being initiated
  loader: false.// Whether the request is complete
  success: false.// Whether the request was successful
  message: ' '  // The request failed
}

// Simplify Redux
const logupReducer = handleActions({
  // Different results return different states
  [logup]: (state, action) = > ({loadering: true.loader: false.success: false.message: ' ' }),
  [logup_success]: (state, action) = > ({loadering: false.loader: true.success: true.message: ' ' }),
  // If the request fails, you need to pass a piece of data to the directive in the action.payload
  [logup_fail]: (state, action) = > ({loadering: false.loader: true.success: false.message: action.payload }),
  [logup_reset]: (state, action) = > ({loadering: false.loader: false.success: false.message: ' ' })
}, logupDate)

export default logupReducer
Copy the code
/ / SRC/store/reducers/index, js will merge into registration related instructions

// Introduce the module method
import { connectRouter } from "connected-react-router"
// Import the reducer merge method
import { combineReducers } from "redux"
// Import the reducer to merge
import testReducer from "./text"
import logupReducer from './logup.reducer'

// Merge all reducer
// createRootReducer is a function, do not change the name
const createRootReducer = history= > combineReducers({
  test: testReducer,
  // Routing information
  router: connectRouter(history),
  logup: logupReducer
})

/ / export
export default createRootReducer
Copy the code

Start the back-end server

The database folder is stored in the course folder – server

  • Install dependency: NPM I
  • Start the mongo
  • Start the server: NPM start

The interface documentation is stored in the PPT folder of the course folder

Configuring saga Middleware

Create a sagas directory in the store directory to store the Saga files

The sagas directory creates the saga file associated with the registration

Intercept initiation registration request instruction, make AXIos request, use try-catch to branch judgment, request success trigger request success instruction, request failure trigger request failure instruction

Sagas directory to create rootsaga file to merge saga (all method)

Register middleware in index.js under store

/ / SRC/store/sagas/logup saga. Js file writing new registration related saga

// Register the component saga import method
import {takeEvery ,put} from 'redux-saga/effects'
// Import all required instructions
import { logup, logup_fail, logup_success } from '.. /actions/logup.action'
// Introduce axios rutting request
import axios from 'axios'
// Imports the current environment request address prefix
import { API } from '.. /.. /config'

// Invoke the callback function after intercepting the request instruction
function* handleLogup(action) {
  // use try-catch to determine the condition
  try {
    // Axios initiates the registration request
    yield axios.post(`${API}/signup`, action.payload)
    console.log('Registration successful')
    // Request success triggers request success instruction
    yield put(logup_success())
  } catch (error) {
    console.log('Registration failed')
    // Request failure triggers the request failure command
    yield put(logup_fail({mesage: 'Registration failed'}}}))// saga intercepts the request and triggers the corresponding function
export default function* logupSaga() {
  yield takeEvery(logup, handleLogup)
}
Copy the code
/ / SRC/store/sagas/root of saga. Js merger of saga

// introduce the all method to merge saga
import { all } from 'redux-saga/effects'
// Introduce saga that needs to be merged
import logupSaga from './logup.saga'

// Call the method to merge saga and export it
export default function* rootSaga() {
  yield all([logupSaga()])
}
Copy the code
// SRC /store/index.js enables saga middleware and implements browser plug-in functions

// Create store method
import { createStore, applyMiddleware } from "redux";
Reducer to use
import createRootReducer from "./reducers"
import { createBrowserHistory } from 'history'
import { routerMiddleware } from 'connected-react-router'
// Introduce saga middleware
import reduxSaga from 'redux-saga'
// Introduce merged saga
import rootSaga from "./sagas/root.saga"
// Redux-devtools-extension specifies how to configure the browser plug-in
import { composeWithDevTools } from 'redux-devtools-extension'

/ / create a saga
const saga = reduxSaga()
/ / export history
export const history = createBrowserHistory()

// Create store repository
const store = createStore(
  createRootReducer(history),
  // The middleware monitors route changes
  // composeWithDevTools wraps around middleware to implement browser plug-in functionality
  composeWithDevTools(applyMiddleware(routerMiddleware(history), saga))
)
/ / implementation of saga
saga.run(rootSaga)

export default store
Copy the code

Verify whether the registered Reducer flow can run

Verify in the registered component (useDispatch)

The Form component triggers the initiate registration directive when it fires the onFinish event

The user fills in the data when the command is triggered

This may need to be viewed using MongoDB Compass software

If the browser plug-in redux-devtools-extension cannot view the redux status, you need to set the redux status in store

// Introduce composeWithDevTools wrapped middleware to make use of the Redux Devtools plugin functionality
import { composeWithDevTools } from 'redux-devtools-extension'

export constStore = createStore(data,// Wrap the middleware with methods
  composeWithDevTools(applyMiddleware(...))
)
Copy the code
/ / SRC/Components/core/Logup js registered component to get instructions and to trigger these request is submitted

import React from 'react'
// Import the layout container
import Layout from './Layout'
// Import the UI component
import { Form, Input, Button } from 'antd'
// The import method is used to get instructions
import { useDispatch } from 'react-redux'
// Import the directive name
import { logup } from '.. /.. /store/actions/logup.action'

// Register the component
function Logup() {
  // Get all instructions
  const dispatch = useDispatch()
  // Form submission method, the form will automatically pass the data filled in by the user as an argument - value
  const handleOnFinish = (value) = > {
    // Execute the request registration directive directly and pass the data to the directive
    dispatch(logup(value))
  }
  return (
    // Export the layout container, passing title and subTitle
    <Layout  title='registered' subTitle='Set up an account.'>{/* form, add form submission event */}<Form onFinish={handleOnFinish}>
        <Form.Item
          label="Login nickname"
          name="name"/ / checkrules={[{ required: true.message:'Please enter a user name! '}}] >
          <Input />
        </Form.Item>
        <Form.Item
          label='Login password'
          name="password"
          rules={[{ required: true.message:'Please enter your password! '}}] >
          <Input.Password />
        </Form.Item>
        <Form.Item
          label="E-mail"
          name="email"
          rules={[{ required: true.message:'Please enter email! '}}] >
          <Input />
        </Form.Item>
        <Form.Item wrapperCol={{ offset: 8.span: 16}} >
          <Button type="primary" htmlType="submit">registered</Button>
        </Form.Item>
      </Form>
    </Layout>)}export default Logup

Copy the code

The state combines with the registry component

Goal:

  • Sending a registration request – Displaying loading
  • Successful registration – Clear the form and display a success message
  • Registration failure – Failure message is displayed
  • Off page – Reset registration status

Get registration status information in the component (useSelector)

Set a signal value to determine whether a registration request is currently being made

To clear the form, get the form object, call the relevant method (from.usefrom), and add the From attribute (From) to the From.

Reset the form (from.resetfields)

Two properties need to be monitored for successful registration (useEffect)

After successful registration, call method to reset the form, and then create method pop-up prompt, use the result component, use the button in the result component, click it to jump to the login interface (Link)

If the registration fails, the result component is also required. The registration failure information is taken from the status, and the server return information is filled in here

Put the entire form in a single function and return to the form

If you leave the registration page and do not reset the registration status, the status of the last registration will affect the current registration

Add monitoring directly to the page, triggering a reset command when the page loads, which resets the state

/ / SRC/Components/core/Logup js registered Components, combined with registration status for binding, according to the state to achieve different results

import React, { useEffect } from 'react'
// Import the layout container
import Layout from './Layout'
// Import the UI component
import { Form, Input, Button, Spin, Result } from 'antd'
// The import method is used to get instructions
import { useDispatch, useSelector } from 'react-redux'
// Import the directive name
import { logup, logup_reset } from '.. /.. /store/actions/logup.action'
// Import method: route forward
import { Link } from 'react-router-dom'

// Register the component
function Logup() {
  // Get all instructions
  const dispatch = useDispatch()
  // Get the status
  const {loadering, loader, success, message} = useSelector(state= > state.logup)
  // Get the form element
  const [form] = Form.useForm()
  // Lifecycle functions
  useEffect(() = > {
    // If registration is successful - reset the form
    if (loader && success) form.resetFields()
  }, [loader, success]) // eslint-disable-line 
  // Lifecycle functions
  useEffect(() = > {
    return () = > {
      // Resets the status directive when the component is destroyed
      dispatch(logup_reset())
    }
  }, [])  // eslint-disable-line 
  // The effect is waiting during the registration process
  const loadingShow = () = > {
    if (loadering) return <Spin />
  }
  // Register success function
  const successShow = () = > {
    // The registration is successful
    if (loader && success) return (
      <Result
        status="success"
        title="Registration successful"
        extra={[// Add login button jump login <Button type="primary" key="console"><Link to='/login'>The login</Link></Button>]} / >)}// Failed to register the function
  const FailShow = () = > {
    // The result of registration failure is displayed
    if(loader && ! success)return (
      <Result
        status="warning"
        title="Registration failed"
        subTitle={message.message}
      />)}// Form submission method, the form will automatically pass the data filled in by the user as an argument - value
  const handleOnFinish = (value) = > {
    // Execute the request registration directive directly and pass the data to the directive
    dispatch(logup(value))
  }
  // Encapsulate the entire form individually
  const jsx = () = > (
    <Form form={form} onFinish={handleOnFinish}>} {loadingShow()} {successShow()} {FailShow()}<Form.Item
        label="Login nickname"
        name="name"/ / checkrules={[{ required: true.message:'Please enter a user name! '}}] >
        <Input />
      </Form.Item>
      <Form.Item
        label='Login password'
        name="password"
        rules={[{ required: true.message:'Please enter your password! '}}] >
        <Input.Password />
      </Form.Item>
      <Form.Item
        label="E-mail"
        name="email"
        rules={[{ required: true.message:'Please enter email! '}}] >
        <Input />
      </Form.Item>
      <Form.Item wrapperCol={{ offset: 8.span: 16}} >
        <Button type="primary" htmlType="submit">registered</Button>
      </Form.Item>
    </Form>
  )
  return (
    // Export the layout container, passing title and subTitle
    <Layout  title='registered' subTitle='Set up an account.'>{/* Call method to insert Form */} {JSX ()}</Layout>)}export default Logup

Copy the code
/ / SRC/store/sagas/logup saga. Js modified registered saga, can let the state failed to get the information

// Register the component saga import method
import {takeEvery ,put} from 'redux-saga/effects'
// Import all required instructions
import { logup, logup_fail, logup_success } from '.. /actions/logup.action'
// Introduce axios rutting request
import axios from 'axios'
// Imports the current environment request address prefix
import { API } from '.. /.. /config'

// Invoke the callback function after intercepting the request instruction
function* handleLogup(action) {
  // use try-catch to determine the condition
  try {
    // Axios initiates the registration request
    yield axios.post(`${API}/signup`, action.payload)
    console.log('Registration successful')
    // Request success triggers request success instruction
    yield put(logup_success())
  } catch (error) {
    // Request failure triggers a request failure directive, which passes the error message returned by request failure
    yield put(logup_fail({message: error.response.data.error}))
  }
}

// saga intercepts the request and triggers the corresponding function
export default function* logupSaga() {
  yield takeEvery(logup, handleLogup)
}
Copy the code

The user login

To implement user login and store user information (localstorage.setitem), convert the character string

The form commits (onFinish) and sends a login request to the interface

After a successful login, you need to switch to another page. Determine the user role. Common user -0 and administrator – 1 go to different pages

Create a new jump instance (useHistory) and finally use the push method to jump

/ / SRC/Components/core/Login. The Login js component Login authentication, data localization, routing, jump

import React from 'react'
// Introduce a common layout container
import Layout from './Layout'
// Import UI components
import { Form, Input, Button, notification } from 'antd'
/ / introduce axios
import axios from 'axios'
// Introduce the axios prefix
import { API } from '.. /.. /config'
// Import method route jump
import { useHistory } from 'react-router-dom'

// Login component
function Login() {
  // Create a routing object
  const history = useHistory()
  // Login form submission method
  const onFinish = async (value) => {
    // Use try-catch to catch errors
    try {
      // Request the login interface, pass the parameters
      const { data } = await axios.post(`${API}/signin`, value)
      // Store the data to the browser
      localStorage.setItem('lagou'.JSON.stringify(data))
      // Jump to different routes according to the user role
      if (data.user.role === 0) {
        history.push('./user/dashboard')}else if (data.user.role === 1) {
        history.push('./admin/dashboard')}}catch (error) {
      // An error message is displayed
      notification.open({
        message: 'Login failed'.description: error.response.data.error
      })
    }
  }
  return (
    // Export the layout container, passing title and subTitle
    <Layout  title='login' subTitle='Please log in to your account'>{/ * * /} forms<Form onFinish={onFinish}>
        <Form.Item
          label="E-mail"
          name="email"/ / checkrules={[{ required: true.message:'Please enter email! '}}] >
          <Input />
        </Form.Item>
        <Form.Item
          label="Login password"
          name="password"
          rules={[{ required: true.message:'Please enter your password! '}}] >
          <Input.Password />
        </Form.Item>
        <Form.Item wrapperCol={{ offset: 8.span: 16}} >
          <Button type="primary" htmlType="submit">The login</Button>
        </Form.Item>
      </Form>
    </Layout>)}export default Login
Copy the code

Displays menu bar options based on user login status

Login and registration are not displayed if the current user is not logged in

Create two new methods in the navigation menu component

Used to return to the login registration component

Used to return to the Dashboard component

Create a directory for public methods in the SRC directory and create a new file to write to determine whether the user is logged in to the method

The title determines whether to log in based on the result returned by the method, so different methods are executed to return different structures

In addition, you can change the Dashboard routing address based on the returned user role

// SRC /method/ loginornot. js Creates a public method for file storage and adds a method to determine whether to login

// check whether you are logged in
export const loginOrNot = () = > {
  // Get local login information
  const data = JSON.parse(localStorage.getItem('lagou'))
  // If there is login information, login information is directly returned
  if (data) return data
  // No login information returns false
  return false
}
Copy the code
/ / SRC/Components/core/Navgation js, the introduction of the above methods according to the method of dynamically adding different structure

import React from 'react'
// Import the navigation component
import { Menu } from 'antd'
// Introduce a method to get stre status
import { useSelector} from 'react-redux'
// Introduce a jump route method
import { Link } from 'react-router-dom'
// Import method - check whether login
import { loginOrNot } from '.. /.. /method/loginOrNot'

// Top navigation component
function Navgation() {
  // Calling the method returns information (login information if logged in, false if not logged in)
  const data = loginOrNot()
  // Get the status - routing information
  const state = useSelector(state= > state.router)
  // Return to the registration and login structures
  const loginRegisterShow = () = > {
    return (
      <>
        <Menu.Item key='/logIn'>
          <Link to='/logIn'>The login</Link>
        </Menu.Item>
        <Menu.Item key='/logUp'>
          <Link to='/logUp'>registered</Link>
        </Menu.Item>
      </>)}// Return to the dashboard structure after login
  const DashboardShow = () = > {
    // Set different values depending on the type of user returned
    const keyAndTo = data.user.role ? '/admin/dashboard' : '/user/dashboard'
    return (
      <>{/* Use dynamic parameters directly */}<Menu.Item key={keyAndTo}>
          <Link to={keyAndTo}>The dashboard</Link>
        </Menu.Item>
      </>)}return (
    <div>{/* Use navigation component, mode - Landscape, selectedKeys - Set selected (array uses current routing information) */}<Menu mode='horizontal' selectedKeys={[state.location.pathname]}>{/* key corresponds to the above selectedKeys */}<Menu.Item key='/'>{/* Set click jump route */}<Link to='/'>Home page</Link>
        </Menu.Item>
        <Menu.Item key='/shop'>
          <Link to='/shop'>List of goods</Link>
        </Menu.Item>{/* dynamic structure, according to whether to login */} {data? DashboardShow() : loginRegisterShow()}</Menu>
    </div>)}export default Navgation
Copy the code

Create a protected Dashboard component

Access is not allowed if the user has not logged in

  • Create two Dashboard components in the admin directory, one for a common user and one for an administrator
  • Add routing configuration to both components
  • Create a new component as a routing guard package component (remember to pass routing information), if the login is not tuned to the login page
  • For both components, a routing guard needs to be created. Admindashboard needs to determine whether the role is an administrator
/ / SRC/Components/admin/UserDashboard js new user information Components

// Layout the container
import Layout from '.. /core/Layout'
import React from 'react'

// User information component - dashboard
function UserDashboard() {
  return (
    // Use layout containers to pass data
    <Layout title='User Information' subTitle='Welcome, dear user.'>The average user</Layout>)}export default UserDashboard
Copy the code
/ / SRC/Components/admin/AdminDashboard js new administrator information component

import React from 'react'
// Layout the container
import Layout from '.. /core/Layout'

// Administrator information component - dashboard
function AdminDashboard() {
  return (
    // Use layout containers to pass data
    <Layout title='User Information' subTitle='Well done, administrator.'>The administrator</Layout>)}export default AdminDashboard
Copy the code
/ / SRC/Components/admin/GuardUserDashboard js user information component routing guards

import React from 'react'
import { Redirect, Route } from 'react-router-dom/cjs/react-router-dom.min'
import { loginOrNot } from '.. /.. /method/loginOrNot'

// User information routing guard component, parameter using destruct assignment
function GuardUserDashboard({component: Component, ... test}) {
  // Get the login information
  const data = loginOrNot()
  return (
    <>{/* Route guard */}<Route {. test} render={ (props) = >If (data && data.user.role === 0) {return<Component {. props} / >} // No color jump login return<Redirect to='/login' />}} / ></>)}export default GuardUserDashboard
Copy the code
/ / SRC/Components/admin/GuardAdminDashboard js administrator information routing guards

import React from 'react'
import { Redirect, Route } from 'react-router-dom/cjs/react-router-dom.min'
import { loginOrNot } from '.. /.. /method/loginOrNot'

// Administrator information routing guard component
function GuardAdminDashboard({component: Component, ... test}) {
  // Get the login information
  const data = loginOrNot()
  return (
    <>{/* Route guard */}<Route {. test} render={ (props) = >If (data && data.user.role) return<Component {. props} / >// Otherwise return login return<Redirect to='/login' />}} / ></>)}export default GuardAdminDashboard
Copy the code
// SRC /Components/ routes.js Route Components Add two user information Components and use route guards

import React from 'react'
BrowserRouter is similar to HashRouter and is more recommended
import { Switch, Route } from 'react-router-dom'
import AdminDashboard from './admin/AdminDashboard'
import GuardAdminDashboard from './admin/GuardAdminDashboard'
import GuardUserDashboard from './admin/GuardUserDashboard'
import UserDashboard from './admin/UserDashboard'
// Import the routing component
import Home from './core/Home'
import Login from './core/Login'
import Logup from './core/Logup'
import Shop from './core/Shop'

function Routes() {
  return (
    // Enable the routing function for the package.
      // {/* Avoid writing errors in the same route */}
      <Switch>{/* Route, the first route is the default route, exact match */}<Route path="/" component={Home} exact />
        <Route path="/shop" component={Shop} />
        <Route path="/login" component={Login} />
        <Route path="/logup" component={Logup} />{/* Use route guard */}<GuardUserDashboard path="/user/dashboard" component={UserDashboard} />
        <GuardAdminDashboard path="/admin/dashboard" component={AdminDashboard} />
      </Switch>)}export default Routes
Copy the code

Administrator component adds links and administrator information

  • Using the component library raster system, 4 on the left and 20 on the right, you can set the clearance around (but you don’t need to set it here)
  • Use the navigation menu on the left to add three links: Add category, Add Item, order list (export using function)
  • Add ICONS to links, using component libraries
  • Add a title above the connection, using the composition function of the component library
  • Use description list component to display administrator information on the right (export using function)
/ / SRC/Components/admin/AdminDashboard js fill the administrator component content

import { Col, Row, Menu, Typography, Descriptions } from 'antd'
import React from 'react'
// Layout the container
import Layout from '.. /core/Layout'
import { PlusOutlined, AppstoreAddOutlined, UnorderedListOutlined } from '@ant-design/icons'
import { loginOrNot } from '.. /.. /method/loginOrNot'
const { Title } = Typography

// Administrator information component - dashboard
function AdminDashboard() {
  // Display the function on the left
  const leftShow = () = > {
    return (
      <>
        <Title level={5}>Functional management</Title>
        <Menu>
          <Menu.Item><PlusOutlined />Add the classification</Menu.Item>
          <Menu.Item><AppstoreAddOutlined />Add the goods</Menu.Item>
          <Menu.Item><UnorderedListOutlined />The order list</Menu.Item>
        </Menu>
      </>)}// Display the function on the right
  const rightShow = () = > {
    // Get user login information
    const {user:{name, email}} = loginOrNot()
    return (
      <Descriptions title="Personal Information" bordered>
        <Descriptions.Item label="Nickname">{name}</Descriptions.Item>
        <Descriptions.Item label="E-mail">{email}</Descriptions.Item>
        <Descriptions.Item label="Role">The administrator</Descriptions.Item>
      </Descriptions>)}return (
    // Use layout containers to pass data
    <Layout title='User Information' subTitle='Well done, administrator.'>
      {/* 行 */}
      <Row>{/* column, call function render */}<Col span={4}>{leftShow()}</Col>
        <Col span={20}>{rightShow()}</Col>
      </Row>
    </Layout>)}export default AdminDashboard
Copy the code

Create add category component

Admin directory new add classification components, introduce layout containers, add routing rules, use routing guards

Add Click To add a classified route

Add a form, and the form adds a submit event

So let’s implement it together

Realize the function of adding categories

Use AXIos to initiate the request and determine whether data is present

Note that the token and user ID need to be passed

-message indicates that the user is successfully added

Add a button to return to the admin page

// SRC /Components/ routes.js Route add Add class, use route guard

import React from 'react'
BrowserRouter is similar to HashRouter and is more recommended
import { Switch, Route } from 'react-router-dom'
import AddSort from './admin/AddSort'
import AdminDashboard from './admin/AdminDashboard'
import GuardAdminDashboard from './admin/GuardAdminDashboard'
import GuardUserDashboard from './admin/GuardUserDashboard'
import UserDashboard from './admin/UserDashboard'
// Import the routing component
import Home from './core/Home'
import Login from './core/Login'
import Logup from './core/Logup'
import Shop from './core/Shop'

function Routes() {
  return (
    // Enable the routing function for the package.
      // {/* Avoid writing errors in the same route */}
      <Switch>{/* Route, the first route is the default route, exact match */}<Route path="/" component={Home} exact />
        <Route path="/shop" component={Shop} />
        <Route path="/login" component={Login} />
        <Route path="/logup" component={Logup} />{/* Use route guard */}<GuardUserDashboard path="/user/dashboard" component={UserDashboard} />
        <GuardAdminDashboard path="/admin/dashboard" component={AdminDashboard} />
        <GuardAdminDashboard path="/admin/addsort" component={AddSort} />
      </Switch>)}export default Routes
Copy the code
/ / SRC/Components/admin/AdminDashboard js dashboard Components, click add category hop routing

import { Col, Row, Menu, Typography, Descriptions } from 'antd'
import React from 'react'
// Layout the container
import Layout from '.. /core/Layout'
import { PlusOutlined, AppstoreAddOutlined, UnorderedListOutlined } from '@ant-design/icons'
import { loginOrNot } from '.. /.. /method/loginOrNot'
import { Link } from 'react-router-dom/cjs/react-router-dom.min'
const { Title } = Typography

// Administrator information component - dashboard
function AdminDashboard() {
  // Display the function on the left
  const leftShow = () = > {
    return (
      <>
        <Title level={5}>Functional management</Title>
        <Menu>{/* Click to add category component */}<Menu.Item><Link to='/admin/addsort'><PlusOutlined />Add the classification</Link></Menu.Item>
          <Menu.Item><AppstoreAddOutlined />Add the goods</Menu.Item>
          <Menu.Item><UnorderedListOutlined />The order list</Menu.Item>
        </Menu>
      </>)}// Display the function on the right
  const rightShow = () = > {
    // Get user login information
    const {user:{name, email}} = loginOrNot()
    return (
      <Descriptions title="Personal Information" bordered>
        <Descriptions.Item label="Nickname">{name}</Descriptions.Item>
        <Descriptions.Item label="E-mail">{email}</Descriptions.Item>
        <Descriptions.Item label="Role">The administrator</Descriptions.Item>
      </Descriptions>)}return (
    // Use layout containers to pass data
    <Layout title='User Information' subTitle='Well done, administrator.'>
      {/* 行 */}
      <Row>{/* column, call function render */}<Col span={4}>{leftShow()}</Col>
        <Col span={20}>{rightShow()}</Col>
      </Row>
    </Layout>)}export default AdminDashboard
Copy the code
/ / SRC/Components/admin/AddSort js to add new component classification

import { Form, Input, Button, message } from 'antd'
import axios from 'axios'
import React from 'react'
import { Link } from 'react-router-dom'
import { API } from '.. /.. /config'
import { loginOrNot } from '.. /.. /method/loginOrNot'
import Layout from '.. /core/Layout'

// Add a category component
function AddSort() {
  // Click the Add Category button event
  const onFinish = value= > {
    // Get user information
    const {token, user:{_id}} = loginOrNot()
    // Determine whether the user has filled in the data
    if(value.name) {
      // Request the interface and pass the parameters
      axios.post(`${API}/category/create/${_id}`, value, {
        headers: {
          Authorization: `Bearer ${token}`
        }
      }).then(rse= > {
        // A message is displayed successfully
        message.success(Add "`${rse.data.name}"Classification success ')}}}return (
    <Layout title='Add category'>{/* Add commit event */}<Form onFinish={onFinish}>
        <Form.Item label='Category name' name='name'>
          <Input />
        </Form.Item>
        <Form.Item>
          <Button type="primary" htmlType="submit">Add the classification</Button>
        </Form.Item>
      </Form>{/* Return to dashboard button */}<Button><Link to='/admin/dashboard'>Return to dashboard</Link></Button>
    </Layout>)}export default AddSort
Copy the code

Create add goods component

Admin directory new add commodity components, introduce layout containers, add routing rules, use routing guards

Add the Form component. In the component, add the cover, name, description, price, category, quantity, and book

Upload product cover using upload component (write structure first and deal with later)

Get category list

The Hook Hook function is used to retrieve the classified data after the page is loaded

You also need to store state, using hook functions

Use AXIos to get the categories, noting that async is used to set up asynchronous functions

Add structure by iterating through the obtained list in the category list

Manually dump some categories from the teacher’s files

Set the first one please select category as default display

Realize the function of adding goods

Process the product cover upload, click select will be submitted immediately, we want to prevent immediate submission behavior (beforupload-false)

You need to get the user cover (beforUpload parameter) and form submission data (onFinish) before submitting.

Add all the data to a formData object before committing

Login data is required to upload and submit data

A message is displayed after the adding succeeds

Empty form

The user page is displayed

// SRC /index.js turns off strict mode to avoid certain errors

import React from 'react'
import ReactDOM from 'react-dom'
// Import the routing component
import Routes from './Components/Routes'
// Introduce methods to pass the store repository
import { Provider } from 'react-redux'
/ / into the store
import store, { history }  from './store'
import { ConnectedRouter } from 'connected-react-router'


ReactDOM.render(
  // Cancel strict mode to avoid errors
  // <React.StrictMode>
    / / {/ * to pass down the store warehouse, the official opening * /}
    <Provider store={store}>{/* Wrapper implementation monitors route changes */}<ConnectedRouter history={history}>{/* Replace APP with routing component */}<Routes />
      </ConnectedRouter>
    </Provider>.// </React.StrictMode>,
  document.getElementById('root'))Copy the code
// SRC /Components/ routes.js Add new configuration information - add goods

import React from 'react'
BrowserRouter is similar to HashRouter and is more recommended
import { Switch, Route } from 'react-router-dom'
import AddSort from './admin/AddSort'
import AddWares from './admin/AddWares'
import AdminDashboard from './admin/AdminDashboard'
import GuardAdminDashboard from './admin/GuardAdminDashboard'
import GuardUserDashboard from './admin/GuardUserDashboard'
import UserDashboard from './admin/UserDashboard'
// Import the routing component
import Home from './core/Home'
import Login from './core/Login'
import Logup from './core/Logup'
import Shop from './core/Shop'

function Routes() {
  return (
    // Enable the routing function for the package.
      // {/* Avoid writing errors in the same route */}
      <Switch>{/* Route, the first route is the default route, exact match */}<Route path="/" component={Home} exact />
        <Route path="/shop" component={Shop} />
        <Route path="/login" component={Login} />
        <Route path="/logup" component={Logup} />{/* Use route guard */}<GuardUserDashboard path="/user/dashboard" component={UserDashboard} />
        <GuardAdminDashboard path="/admin/dashboard" component={AdminDashboard} />
        <GuardAdminDashboard path="/admin/addsort" component={AddSort} />
        <GuardAdminDashboard path="/admin/addwares" component={AddWares} />
      </Switch>)}export default Routes
Copy the code
/ / SRC/Components/admin/AdminDashboard js add click to jump to add commodity routing

import { Col, Row, Menu, Typography, Descriptions } from 'antd'
import React from 'react'
// Layout the container
import Layout from '.. /core/Layout'
import { PlusOutlined, AppstoreAddOutlined, UnorderedListOutlined } from '@ant-design/icons'
import { loginOrNot } from '.. /.. /method/loginOrNot'
import { Link } from 'react-router-dom/cjs/react-router-dom.min'
const { Title } = Typography

// Administrator information component - dashboard
function AdminDashboard() {
  // Display the function on the left
  const leftShow = () = > {
    return (
      <>
        <Title level={5}>Functional management</Title>
        <Menu>{/* Click to add category component */}<Menu.Item><Link to='/admin/addsort'><PlusOutlined />Add the classification</Link></Menu.Item>{/* Click jump to add commodity component */}<Menu.Item><Link to='/admin/addwares'><AppstoreAddOutlined />Add the goods</Link></Menu.Item>
          <Menu.Item><UnorderedListOutlined />The order list</Menu.Item>
        </Menu>
      </>)}// Display the function on the right
  const rightShow = () = > {
    // Get user login information
    const {user:{name, email}} = loginOrNot()
    return (
      <Descriptions title="Personal Information" bordered>
        <Descriptions.Item label="Nickname">{name}</Descriptions.Item>
        <Descriptions.Item label="E-mail">{email}</Descriptions.Item>
        <Descriptions.Item label="Role">The administrator</Descriptions.Item>
      </Descriptions>)}return (
    // Use layout containers to pass data
    <Layout title='User Information' subTitle='Well done, administrator.'>
      {/* 行 */}
      <Row>{/* column, call function render */}<Col span={4}>{leftShow()}</Col>
        <Col span={20}>{rightShow()}</Col>
      </Row>
    </Layout>)}export default AdminDashboard
Copy the code
/ / SRC/Components/admin/AddWares js add new goods Components

import { Form, Input, Button, Upload, Select, Radio, message } from 'antd'
import { UploadOutlined } from '@ant-design/icons'
import { useEffect, useState } from 'react'
import Layout from '.. /core/Layout'
import axios from 'axios'
import { API } from '.. /.. /config'
import { loginOrNot } from '.. /.. /method/loginOrNot'
import { useHistory } from 'react-router-dom/cjs/react-router-dom.min'

// Add a commodity component
function AddWares() {
  // List of goods by category
  let [list, listSet] = useState([])
  // Upload the cover
  let [flie, flieSet] = useState()
  // Get the form
  const [form] = Form.useForm()
  // Get the route jump method
  const history = useHistory()
  // The hook function
  useEffect(() = > {
    // Handle asynchronous functions, where the asynchronous process is written as a single function
    async function loadList() {
      // Make a request to get a list of all categories
      const { data } =  await axios.get(`${API}/categories`)
      // Put the list in the state
      listSet(data)
    }
    // Call function execution
    loadList()
  }, [])
  // Upload the component configuration
  const props = {
    // Upload related, the parameter is to upload the image itself
    beforeUpload(e) {
      // Store the image information
      flieSet(e)
      // Return false to avoid automatic uploads
      return false}}// Click Submit event
  const onFinish = value= > {
    // Get user information
    const {token, user:{_id}} = loginOrNot()
    // Create formData instance as required by the interface
    const formData = new FormData()
    // Add the form data to the instance object
    for(let key in value) {
      formData.append(key, value[key])
    }
    // Add the image information to the instance object
    formData.append('photo', flie)
    // Initiate a request to add an item
    axios.post(`${API}/product/create/${_id}`, formData, {
      headers: {
        Authorization: `Bearer ${token}`
      }
    }).then(rse= > {
      // A message is displayed successfully
      message.success(Add "`${rse.data.name}Commodity success)
      // Clear the form
      form.resetFields()
      // Automatically jumps back to the dashboard
      history.push('/admin/dashboard')})}return (
    <Layout title='Add goods'>{/* Set form to get From component, initialValues to default, onFinish submission is a shame */}<Form form={form} initialValues={{category: '- 1'}} onFinish={onFinish} >
        <Form.Item >{/* Add props set parameter */}<Upload {. props} >
            <Button icon={<UploadOutlined />}> Upload cover</Button>
          </Upload>
        </Form.Item>
        <Form.Item label='name' name='name'>
          <Input />
        </Form.Item>
        <Form.Item label='description' name='description'>
          <Input />
        </Form.Item>
        <Form.Item label='price' name='price'>
          <Input />
        </Form.Item>
        <Form.Item label='Category of ownership' name='category'>
          <Select>
            <Select.Option value='1'>Please select a category</Select.Option>} {list.map(item => {return (<Select.Option key={item._id} value={item._id}>{item.name}</Select.Option>)})}</Select>
        </Form.Item>
        <Form.Item label='number' name='quantity'>
          <Input />
        </Form.Item>
        <Form.Item label='Do YOU need transportation?' name='shipping'>
          <Radio.Group>
            <Radio value={true}>is</Radio>
            <Radio value={false}>no</Radio>
          </Radio.Group>
        </Form.Item>
        <Form.Item>
          <Button type="primary" htmlType="submit">Add the goods</Button>
        </Form.Item>
      </Form>
    </Layout>)}export default AddWares
Copy the code