portal

  • Vite + React + TS
  • Github address (Github updates faster than documents, with lots of comments added to documents) Github address

preface

  • I changed this article many times and added a lot of complicated packages, but it was very unfriendly to students who were just learning React + TS. Because it was not easy to understand, I deleted and deleted it. I tried to write it in a way that everyone could understand it

  • Complex function encapsulation will explain in detail in the series, then followed by in-depth study, step by step in the project most of the code has detailed notes, I hope you don’t think the meng, because myself at the time of beginning to find a open source project, making a lot of project of encapsulation is very good, but for the small white is very stupid, have to look for a long time, So I this tutorial, will try to speak in detail, according to the document, the project can run, notes to write detailed, and then cooperate with live, explain clearly.

  • Ts everyone do not feel difficult, go to the official website to look at the basic usage, you can, encountered do not understand the grammar directly check, use a few times will be good.

  • React the same way, don’t underestimate your ability and practice lots of code. Don’t understand on the ask, won’t check, one to two natural meeting.

  • This one is mainly about

    • Use of dummy data jSON-server

    • Simple use of the request interface

    • Simple use of routing

    • Some simple global configuration data

    • Use of internationalization

    • Encapsulation of simple common components

Json – server mock data

  • yarn add json-server -D

  • In the end

    mkdir mock
    cd mock
    touch db.json
    Copy the code
  • Add it to scripts in package.json

    "mock": "json-server mock/db.json --port 3008"
    Copy the code
  • Then run the yarn Mock command to successfully access the interface data we configured in db.json from the console

Request to packaging

Note: process.env should be replaced with import.meta.env

  • The global common configuration files are placed in the config.ts file in the root directory, and currently the project starts with a small amount of configuration information
 /** * Current environment variable */
// process.env is not available in vite
// export const whyEnv = import.meta.env.VITE_REACT_URL || "";
/** * Interface address *@description Env can be the primary environment or a custom address */
export const apiAddress = "http://localhost:3008/";

/** * develop the proxy prefix */
export const proxyApi = "/api";

/** * Interface prefix * Determines whether the prefix is required. * The production environment does not require proxies, and the locally configured proxies are unavailable in the production environment. */
export const urlPrefix = process.env.NODE_ENV === "development" ? proxyApi : "";

Copy the code
  • Umi-request library used in the project, so far I have configured few things, error handling, middleware processing and so on I have deleted, not so complicated at the beginning
   // utils/request.ts

 / * * * * more detailed request network request tool API documentation: https://github.com/umijs/umi-request * /
import umiRequest, { extend } from "umi-request";
import { urlPrefix } from ".. /config";

// Use a prefix to work with the local proxy
export const whyRequest = extend({
  prefix: `${urlPrefix}`});export default umiRequest;
Copy the code
  • Define interface: to communicate with the back segment in advance of the input parameter, the format of the parameter, combined with the TS type prompt, in other places when you can directly see the attributes of the interface definition, very convenient
/** * export interface ILogin {userName: string; pwd: string; } /** * export interface ILoginData {code: number; message: string; token: string; } /** * export const loginApp = (params: ILogin): Promise<ILoginData> => { return whyRequest.get("/login", params); };Copy the code
  • It’s easy to use, call directly, and then we’ll use useRequest() in conjunction with ahooks
loginApp({ userName: "why", pwd: "123" }).then((res) => { if (res.code === 200) { history.push("/home"); } else {message.error(" Wrong username or password!" ); }});Copy the code

Internationalization configuration

  • yarn add react-intl -D
  • For internationalization, we use React-IntL and also need to be compatible with antD and other plugins in Both Chinese and English. When we switch languages, the plugin library also needs to be directly switched to the corresponding language, which is also easy to configure.
  • Let’s go straight to the code
Import {createIntl, IntlProvider} from "react-intl"; import {createIntl, IntlProvider} from "react-intl"; Import antdEnUS from "antd/lib/locale/en_US"; import antdZhCN from "antd/lib/locale/zh_CN"; Import enLn from "./components/ln-en"; import zhLn from "./components/ln-zh-cn"; ** * The Provider that wraps the default locale * LocaleProvider needs to be used in app.tx. * @param props * @returns */ export const LocaleProvider: React.FC = (props) => { return <IntlProvider locale={getLocale()}>{props.children}</IntlProvider>; }; /** * get the current intl object, @param changeIntl Whether g_intl * @returns IntlShape */ const getIntl = (locale? : string, changeIntl? : Boolean) => {// If global g_intl exists and not setIntl calls if (gIntl &&! changeIntl && ! locale) { return gIntl; } // If (locale && localeInfo[locale]) {return createIntl(localeInfo[locale]); } // use the defaultLanguage if (localeInfo[defaultLanguage]) return createIntl(localeInfo[defaultLanguage]); // use zh-cn if (localeInfo["zh-cn"]) return createIntl(localeInfo["zh-cn"]); // if (! locale || !! localeInfo[locale]) { throw new Error( "The current popular language does not exist, please check the locales folder!" ); } // If not, return createIntl({locale: "zh-cn", messages: {},}); }; /** * Language conversion * @Param Descriptor * @param values */ export const formatMessage = (Descriptor: MessageDescriptor, values? : Record<string, any> ) => { if (! gIntl) { setIntl(getLocale()); } return gIntl.formatMessage(descriptor, values); };Copy the code
  • Page use

    1. We need to configure both Chinese and English in the corresponding TS file

    Export default {frontEnd: "Work hard on the front end", switchLan: "Chinese-English shift", switchToEn: "switch to chinese", switchToCh: " switch to english", localLan: "The internationalization of this project is based on", }; Export default {frontEnd: "Work hard ", switchLan:" Switch to Chinese ", switchToEn: "Switch to Chinese ", switchToCh:" Switch to English ", localLan: "Internationalization of this project is based on ",};Copy the code

    2. In the page we simply call formatMessage()

/** * international page *@constructor* /
const LocalePage: React.FC = () = > {
  // This uses useState, which is not needed at all
  const [value, setValue] = React.useState(
    localStorage.getItem("why__locale") | |"zh-cn"
  );
  // Switch to multiple languages
  const onChange = (e: RadioChangeEvent) = > {
    setValue(e.target.value); // In this case, the code has no effect
    setLocale(e.target.value); // Call the switch to multiple languages method and refresh the page
  };
  return (
    <Card title={formatMessage({ id: "switchLan"})}style={{ width: "500px}} ">
      <Radio.Group onChange={onChange} value={value}>
        <Radio value={"zh-cn"} >{formatMessage({ id: "switchToEn" })}</Radio>
        <Radio value={"en"} >{formatMessage({ id: "switchToCh" })}</Radio>
      </Radio.Group>
      <div className={styles.localLan}>
        {formatMessage({ id: "localLan" })}react-intl
      </div>
    </Card>
  );
};
Copy the code
  • Internationalization page

routing

  • React Routing look at this

  • React Routing system is very different from VUE. There is no route navigation front hook. Configure login authentication by yourself.

  • The purpose of routing in our project is to support dynamic routing, routing permissions, configuration stripping, so far is the simplest, bare

Common Component encapsulation

  • How do we encapsulate a common component?

    1. Components that need to be used in multiple places in a project

    2. Components that are not coupled to business, common components for business coupling

    3. All states can be controlled externally, using passed props to control their behavior without exposing their internal structure.

    A well-packaged component hides its internal structure and provides a set of properties that control its behavior. It is necessary to hide the internal structure. Other components have no need to know or depend on the internal structure or implementation details of the componentCopy the code
  • The unified directory in our project is mainly for looking comfortable

  • Directory:

    • Index.tsx main entry file

    • Index. md uses samples for components, necessary code comments, and clearly tells others how to use this common component

How do I use iconfont font ICONS

  • Antd createFromIconfontCN is an easy way to create a font icon in iconfont
  • As shown in the picture below, directly log in to the iconfont website to generate the corresponding JS file. It is good to directly use it in the project. It is very simple

  • Introduction to using NPM for classNames
// If the value is true, add the class name to the attribute, and if the value is false, do not add the class name. <FontIcon className={classNames({[styles.large]: Size === "large", // Return true using CSS. Large, same below [styles.normal]: size === "normal", [styles.small]: size === "small", [styles.disabled]: disabled, }, className )} {... restProps} />Copy the code
  • 1.React.FC is a functional component used in TypeScript as a generic.FC stands for FunctionComponent. In fact, react. FC can be written as react. FunctionComponent:
const App: React.FunctionComponent<{ message: string }> = ({ message }) => (
  <div>{message}</div>
);
Copy the code

2.React.FC contains a generic PropsWithChildren without explicitly declaring the type of props. React.FC<> is explicit for return types, whereas the normal function version is implicit (otherwise additional comments are required).

3.React.FC provides static properties for type checking and auto-completion: displayName, propTypes, and defaultProps (note: defaultProps can be a bit problematic when used with react. FC).

4. When we use React.FC to write React components, we can not use setState, but use useState(), useEffect and other Hook apis.

  • React.FC<> provides a good link to the react. FC<>

Encapsulate the Icon common component

// IconType inherits the react. HTMLAttributes attribute, Export interface IconType extends React.HTMLAttributes<any> {// Type must be tributributes. Error: TS2741: static type check is very nice Property 'type' is missing in type '{}' but required in type 'IconType'. index.tsx(7, 3): 'type' is declared here. type: string; // Icon size, default normal size? : "small" | "normal" | "large" | null; // Optional attribute, size followed by? // Whether to disable disabled? : boolean; } // createFromIconfontCN returns a component const FontIcon = createFromIconfontCN({// Please give the new icon a proper hump name and make sure the word is correct: "//at.alicdn.com/t/font_955172_ymhvgyhjk.js", }); const Icon: React.FC<IconType> = ({ className, size = "normal", disabled, ... RestProps}) => {// We are using classNames to dynamically render the state of the icon, Return (<FontIcon className={classNames({[styles.large]: size === "large", [styles.normal]: size === "normal", [styles.small]: size === "small", [styles.disabled]: disabled, }, className )} {... restProps} /> ); }; // Question to consider: Does this place need to use react.memo? export default React.memo(Icon);Copy the code
  • Use (the iconSelect public component is shown in the screenshot, which is not explained in this article)

conclusion

  • Vite + React + TS
  • Github address (Github updates faster than documents, with lots of comments added to documents) Github address
  • If you have a question, make an issue or add a blogger: Lisawhy0706
  • The next article will focus on some of the more complex components
    • Improve the functionality in the project
    • Handling of common configurations
    • Encapsulation of custom hooks
    • How to design project permissions including routing permissions, button level permissions