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)
-
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
-
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
-
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
-
Start the mongo
/ / start brew services run mongodb-community - Successfully ran 'mongodb-community'.... Indicates successful startup. Copy the code
-
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
-
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
- 1. Database configuration file
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
-
Create projects using scaffolding: NPM install -g create-react-app@4.0.3
-
Create project: NPM init React-app project name, use lagou-carefully selected in the course
-
Installation project dependencies
NPM install antd@4.14.0 axios@0.21.1 moment@2.29.1 redux@4.0.5 axios@0.21.1 antd@4.14.0 antd@4.14.0 redux-devtools-extension@2.13.9
+ 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
-
Clean up unnecessary files, directories, and code in your project
-
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
-
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
-
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
-
Merge the Reducer code and add a new attribute
-
Add the routing middleware when creating the store, where the history is retrieved and used
-
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 redux-actions@2.6.5 simplified code – NPM I redux-actions@2.6.5
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