Project background

Learning opportunity

When it comes to React, it’s not hard to learn it until now. Maybe it’s due to laziness. I feel comfortable lying in vue, so I don’t bother to do anything about it.

Influenced by all of you, I became anxious, so I customized a series of learning plans, trying to stop being an API engineer this year, or I will go back to inherit the family property.

The React project was also written using our background management system as the template. Therefore, if you read my previous VUE3 project, you may feel that how could the React project be so crazy

Attach the github open source project address: viet-React

Learning channels

Personally, I don’t like watching videos. I think it’s too slow and easy to get distracted. I think it’s more fascinating to read documents. So start with the React documentation.

Find the official recommendation for beginners in the official documentation:

If you find the React documentation too fast-paced to get used to, check out Tania Rascia’s React overview. It details the most important React concepts in a beginner friendly way. Check out this overview and come back to the official documentation!

So I read the recommended blog post. It was easy to read, though I read it three times, and then read the react-hooks article about building a CRUD application in React. Then I went back to the React documentation. During this period, if there was something difficult to understand, I would use Baidu to analyze step by step, such as context and hooks. The whole reading comprehension process took a week, of course, this week was after work.

The biggest feeling after reading these is that the JSX structure, which made me unable to watch before, is now a little clearer and less resistant (after writing it for a second time, I don’t reject it completely, but find it interesting to write).

The project practice

Next comes the practical phase

The project build

I use vitE2 directly for scaffolding here, so I can walk normally according to the document process.

Building vite projects with NPM:

$ npm create vite@latest
Copy the code

Select react => react-ts

Then an initial React template project is built (steamed C)

Then download the dependency package:

$ npm install
Copy the code

Then start the development environment:

$ npm run dev
Copy the code

The react project runs as simple as possible. Configure the plugins for the react project step by step.

Routing: React-Router State management: React-Redux HTTP library: AXIos CSS preprocessor: less Date formatting component library: Moment UI component library: Ant Design

Delete the template page files generated in the SCR directory to create the directory structure required for the project:

The routing configuration

This version adds a new API, useRoutes, which can read the routing configuration array and generate the corresponding routing component list. The recipe is similar to vue-Router. I’m just used to the API model:

Create the route management file SRC /router/index.tsx

import LoginPage from ". /.. /views/login";
import LayoutPage from ". /.. /views/layout";
import HomePage from ". /.. /views/home";
import LandPage from ". /.. /views/api/land";
import IndustryPage from ". /.. /views/api/industry";
import RolePage from ". /.. /views/sys/role";
import MenuPage from ". /.. /views/sys/menu";

const routes:any = [
  {path: "/login".element: <LoginPage />, isHome: true},
  { 
      path: "/".element: <LayoutPage />.// Set the child route
      children: [
          {path: "/home".element: <HomePage />},
          {path: "/land".element: <LandPage />},
          {path: "/industry".element: <IndustryPage />},
          {path: "/role".element: <RolePage />},
          {path: "/menu".element: <MenuPage />}}]]export default routes
Copy the code

Path: ‘/’ is the default route. After configuring the route list, import the route configuration to the project entry file mian.

Modify the entry file: SRC /main.tsx

import ReactDOM from 'react-dom'
import routes from "./router";
import { useRoutes } from 'react-router-dom';
import {BrowserRouter as Router} from 'react-router-dom'

import './assets/css/index.css'
import 'antd/dist/antd.css';
import zhCN from 'antd/lib/locale/zh_CN';
import { ConfigProvider } from 'antd';

function App() {
  return useRoutes(routes) 
}

const renderApp = () = > {
  ReactDOM.render(
    <ConfigProvider locale={zhCN}>
      <Router>
        <App />
      </Router>
    </ConfigProvider>.document.getElementById('root')
  )
}
renderApp();
Copy the code

Create a function component that passes the route array to useRoutes. UseRoutes can only be used in the Router context, so useRoutes needs to be written to BrowserRouter.

ConfigProvider is an Ant Design internationalization component.

State management

The state manager integrates react-Redux, but ultimately does not use this approach, instead using the context component tree to share data globally, as described later.

Create an entry file: SRC /store/index.tsx

import { configureStore, combineReducers } from '@reduxjs/toolkit';
import { TypedUseSelectorHook, useSelector, useDispatch } from 'react-redux';

import slice from './slices';

const reducer = combineReducers({
  slice
});

export const store = configureStore({
  reducer,
});

export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;

export const useAppDispatch = () = > useDispatch<AppDispatch>();
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;

export default store;
Copy the code

Create data center files: SRC /store/ 4040s.tsx

import { createSlice } from '@reduxjs/toolkit';
import { RootState } from '.. /store';

export interface IGlobalState {
  pageTabActive: any;
  tabsList: Array< > []; }const initialState: IGlobalState = {
  pageTabActive: -1.// ID of the current menu page
  tabsList: [].// List of open TAB pages
  collapsed: window.innerWidth < 1000 // Menu closed
};

const globalSlice = createSlice({
  name: "global",
  initialState,
  reducers: {
    setPageTab: (state, action) = > {
      state.pageTabActive = action.payload || -1
    },
    setTabsList: (state, action) = > {
      state.tabsList = action.payload || []
    }
  }
});

export const selectGlobal = (state: RootState) = > state.slice;

export const {
  setPageTab,
  setTabsList
} = globalSlice.actions;

export default globalSlice.reducer;
Copy the code

Modify the entry file: SRC /main.tsx

.import { Provider } from 'react-redux';
import store from './store/index';

const renderApp = () = > {
  ReactDOM.render(
    <Provider store={store}>.<App />.</Provider>.document.getElementById('root'))}...Copy the code

Components used in the SRC/views/layout/components/c – nav/index TSX

import { useAppDispatch, useAppSelector } from './store';
import { selectGlobal, setPageTab, setTabsList } from './store/slices';
function LayoutNav() {
    const globalState:any = useAppSelector(selectGlobal); / / property
    const dispatch = useAppDispatch(); / / method
    dispatch(setPageTab("1"))
    dispatch(setTabsList([]))
    
    return <div>{globalState.pageTabActive}</div>
}
export default LayoutNav
Copy the code

Here I use the ReduxJS/Toolkit library, which encapsulates some tedious configurations of Redux. The details are still to be explored.

The three redux principles are: 1) single data source 2) state read-only 3) Use functions to perform modifications

I didn’t get too tangled up in redux, because I ended up using the context instead, so I studied the context more, and of course the Redux scheme remained in the project.

Hooks

// Function Welcome(props) {return <h1>Hello, {props. Name}</h1>; Render () {return <h1>Hello, {this.props. Name}</h1>; }}Copy the code

The React component is a function component and a class component. The react component has this, while the function component does not. Class components have a life cycle; function components do not. Class components have state; function components do not.

Before hooks, function components in React were considered only for UI rendering, had no state of their own, no business logic code, and were pure functions.

import {useState} from 'react'
function Welcome() {
  const [name, setName] = useState('Ming')
  
  useEffect(() = > {
    setName('small')
  },[])

  return <h1>Hello, {props.name}</h1>;
}
export default Welcome
Copy the code

Hooks provide function components with useState state, useEffect side effects, useCallback cache functions, etc., which allow an application to write no class components.

The useState state can only be modified by destructing functions. The useEffect side effect can be viewed as a combination of three lifecycle functions in the class component. The second parameter indicates the state changes to be listened for, and if not, all state changes are listened for.

Context

React is a one-way data flow, and data is passed from top to bottom through props. However, this method is extremely cumbersome when the component tree is deep and complex and multiple components need it. Context provides a way to share such values between components without explicitly passing props through each layer of the component tree.

As mentioned above, the project uses Context instead of Redux for global state management, because Context is global to a component tree. Although it is designed to simplify layer-by-layer passing, when all routing components are centralized under one main route, The state of the main routing component can be managed globally through the Context.

import {createContext, useState} from 'react'
import style from './index.module.less'
import LayoutNav from "./components/c-nav/index";
import LayoutMain from "./components/c-main/index";

interface IGlobalState {
  pageTabActive: String;
  tabsList: Array< > []; collapsed: boolean; }const initialState: IGlobalState = {
  pageTabActive: "1".// ID of the current menu page
  tabsList: [] // List of open TAB pages
};

export const MyContext = createContext({})

function App() {
  const [state, setState] = useState(initialState)

  return (
    <MyContext.Provider value={{state, setState}} >
      <div className={style.layoutContainer}>
        <LayoutNav />
        <LayoutMain />
      </div>
    </MyContext.Provider>)}export default App
Copy the code

CreateContext creates a Context object named MyContext, and the component tree matches the Context to the nearest Provider.

Mycontext. Provider is the producer, and the value property is the property that needs to be passed for use by internal components.

How to useContext within a component, I’m using the useContextAPI to get the value of the imported Context object, which can be used just like the state in its own component.

import { MyContext } from ". /.. /.. /index";
function LayoutNav() {
    const{state, setState}:any = useContext(MyContext) setState({... state,tabsList: []});
    console.log(state)
}
Copy the code

There are other uses to explore

The last

React has not been fully learned yet, so please forgive me if there are some mistakes in the above opinions. I will continue to practice through more projects.

Not product frog step, not even thousands of miles not small streams, beyond into rivers and seas