The author of this article Ruoduan. Cn please note the source
-
origin
I am fully responsible for the background management of IM instant chat, a new project of the company in the middle desk system. The front-end technology selection Want to use the relatively new is hot technology – reactHook + react – Router5 + Typescript + (mobx | useContext + useState), as for the brackets later answer, Personally, I think it can replace mobx and Redux state management to some extent
-
This article will cover Typescript, react-hook, and reacthook-tsx (practices)
-
Typescript
- Project structures,
- The type definition
- Application analysis
- .
-
The React – Hook ⭐ ️
- useState
- useEffect
- useContext
- .
-
Hook and Mobx redux, etc., to achieve their own state management
-
The React family don’t explain the stuff in detail.
-
All right, let’s get started
Typescript
React-typescript project scaffolding
The NodeJS environment requires a Not download link
We used the scaffolding create-react-app to build the React-typescript project environment directly
The version must be nodeJS 8+ and Yarn 0.25+
npx create-react-app my-app --typescript
npm init react-app my-app --typescript
yarn create react-app my-app --typescript
Copy the code
Typescript project files
- Here’s a look at some of typescript’s file definitions
./ / SRC./ React-app-env.d. ts // Global declaration tsconfig.json // typescript configuration fileCopy the code
Tsconfig. json: 🌰
{
"compilerOptions": {
"experimentalDecorators": true."target": "es5", // Language compilation target"lib": [
"dom"."dom.iterable"."esnext"]."allowJs": true."skipLibCheck": true."esModuleInterop": true."allowSyntheticDefaultImports": true."strict": true."forceConsistentCasingInFileNames": true."module": "esnext"."moduleResolution": "node"."resolveJsonModule": true."isolatedModules": true."noEmit": true."jsx": "react"// Component syntax environment},"include": [// compile the target directory"src"]},Copy the code
- React-app-env.d. ts is the TypeScript declaration file 🌰 for example: you introduced
jQuery
In the typescript:
$('#dom');
// or
jQuery('#dom');
Copy the code
// ERROR: Cannot find name ‘jQuery’. Error because ts compiler does not know $() or jQuery
We need to define this variable globally with the declare modifier 🌰
declare var jQuery: (selector: string) = > any;
jQuery('#foo');
Copy the code
So we can have fun using jquery
But predecessors trees descendants cool a lot of library community has given me the definition of our installation can be
yarn add @types/jquery --save-dev
We will also use the @types type installation in later projects
You can search TypeSearch for the library type you want
Now that we’ve gotten a first look at Typescript’s project structure, it’s a superset of JS, a progressive language, as stated on the Typescript website. It’s compatible with most of the new syntax in JS and adds types to it
Install antD, React-Router-DOM,…
Yarn add ANTd React-router-dom: 🌰
Note: ⚠️ : react-router-dom needs to install @types oh yarn add @types/react-router-dom –save-dev
Antd Engineering reference
Below let me enter the key ~
React-hook
As we know, React is divided into two components, one is class component, the other is function component
The difference between
The difference between | class | func |
---|---|---|
Define the way | class | func |
state | There are (state) | There is no |
this | There are | There is no |
The statement period | There are | There is no |
terseness | ordinary | A more concise |
By comparison, we can see that traditional function components have no state and lifecycle
So in previous development, functional components were often used as a supplement to simple components
React-hook allows us to use state component state management in functional components. It also enables us to realize the declaration cycle — side effects. In addition, it greatly simplifies the code, making it more concise and easy to understand
userState
Let’s look at the following two pieces of code
import React, { useState } from 'react';
function Example() {
// Declare a state variable called "count"
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={()= > setCount(count + 1)}>
Click me
</button>
</div>
);
}
Copy the code
Is equivalent to
class Example extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
}
render() {
return (
<div>
<p>You clicked {this.state.count} times</p>
<button onClick={()= > this.setState({ count: this.state.count + 1 })}>
Click me
</button>
</div>); }}Copy the code
- You can see we’re importing
useState
Use the array destructor syntax to define two variablescount, setCount
It passes in an initial value of 0, and in the following usage we get rid of the nastythis
Directly available - Conut is our hook variable equal to
state
- SetCount is what we’re looking at
count
The assignment function of theta is equal tothis.setState()
Effect Hook
Effect Hooks allow you to perform side effects in function components
Look at the code below
import React, { useState, useEffect } from 'react';
function Example() {
const [count, setCount] = useState(0);
// Update the page title in the component
useEffect((a)= > {
// Set the page title
document.title = ` digital${count} `;
});
return (
<div>
<p>Digital {count}</p>
<button onClick={()= > setCount(count + 1)}>
+ 1
</button>
</div>
);
}
Copy the code
Equivalent to the class
lass Example extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
}
componentDidMount() {
document.title = ` digitalThe ${this.state.count} `;
}
componentDidUpdate() {
document.title = ` digitalThe ${this.state.count} `;
}
render() {
return (
<div>
<p>Digital {this. State. The count}</p>
<button onClick={()= > this.setState({ count: this.state.count + 1 })}>
+ 1
</button>
</div>); }}Copy the code
We can see the difference in the class component componentDidUpdate we repeat the definition of the life cycle, componentDidMount
-
Why do we use the data in class state?
-
We know that the data defined in state in the class component is going to be rerendered after the data is updated
-
UseEffect calls it after the DOM update has been performed. In this effect, we set the title property of the document, but we can also perform data fetching or call other imperative apis.
-
Note ⚠️ : By default, it is executed after the first render and after each update. (We’ll talk about how to control it later.)
What useEffect does is it simply tells the React component that it needs to do something after rendering, and then it does it after each rendering
Let’s introduce the useEffect implementation for componentDidMount and componentDidUpdate
First of all, we can define multiple Usestates and UseEffects in our function component and they will execute in sequence
The return value of useEffect written earlier determines the type and destruction of this side effect
- Return function: encountered a side effect of clearing
- Return [] Empty array: Effect that runs only once (only when the component is mounted and unmounted)
- Avoid infinite loops
UseEffect = = = componentDidMount 🌰
For example, we want to request data and render it to the page when the page is mounted
let [list, setList] = useEffect([]) // Get the data const getList = async() = > {let res = await axios('xxx')}// Mount side effects only once useEffect((a)= > { getList() }, []) Copy the code
UseEffect = = = componentDidUpdate 🌰
Again, we need to update the mobx subscribed store data to the page in real time
let [list, setList] = useEffect([]) let [data, setData] = useEffect(store.rows) // Get the data const getList = async() = > {let res = await axios('xxx')}// Obtain the data in the store const getStore = (a)= > { @observer letres = store.getxxxxx ... SetData (res)}// Mount side effects only once useEffect((a)= > { getList() }, []) // Side effect functions to be cleared useEffect((a)= > ((a)= > getStore )() ) Copy the code
So far we have basically understood the basic use of reactHook. Here is a simple Redux state management based on Reacthook-usecontext
Other ReactHook implements basic
Redux
Based on the previous useReducer, and createContext, useContext
Let’s take a look at the additional Hook useReducer:
const [state, dispatch] = useReducer(reducer, initialArg, init); Copy the code
It receives a Reducer of the form (state, action) => newState and returns the current state and its corresponding dispatch method. (Not a bit familiar, used redux children’s shoes ~)
-
import * as React from 'react'
const { useContext, useReducer, createContext } = React
// Return the state according to action.reduce
function reducerInAction(state, action) {
if (typeof action.reducer == 'function') {
return action.reducer(state)
}
return state
}
// Process store data
export default function createStore(params) {
const{ _State = {}, reducer } = { ... params,reducer: reducerInAction
}
// Status management data is distributed by createContext
const Appcontext = createContext()
const upReducer = (lastState, action) = > {
// Update the data
let netxState = reducer(lastState, action)
store._state = netxState
return netxState
}
const store = {
_state: _State,
dispatch: undefined.getState: (a)= > {
return store._state
},
useContext: (a)= > {
return useContext(Appcontext)
}
}
// Return the data after processing
const Provider = props= > {
const [state, dispatch] = useReducer(upReducer, _State)
if(! store.dispatch) { store.dispatch =async (action) => {
if (typeof action === 'function') {
await action(dispatch, store.getState())
} else {
dispatch(action)
}
}
}
return <Appcontext.Provider {. props} value={state} />
}
return {
Provider,
store
}
}
Copy the code
Use ⬆ ️
import * as React from 'react'
import HooksRedux from '@/HooksRedux'
const {
Provider,
store
} = _HooksRedux({
State: { name: 'Ming'.age: '18' }
/ / request
const Add_action = (a)= > {
return {
type: 'ADD',
reducer(state) {
return {
...state,
age: state.age + 1}}}Copy the code
@Reference
Ps: That’s basic of Redux, but IN my actual projects I still use MOBx, and its design patterns and object-oriented writing are more comfortable. May refer to
Practice (TSX + Hook)
– I can’t decideAny
– anyscript
Ps: This is certainly not desirable, but in our rapid development process we sometimes have a generic | interface that is uncertain. We can use any for a while and then change later
- Chestnut 🌰
For example, if we want to pass an object to a child component using props, but the object is the interface data, and we’re not sure what the data types and properties of the object are, we can use any for now, and I usually Type TODO any Type in there for later processing.
– React.FC
We can see code like this:
const app: React.FC = () => {
...
}
Copy the code
FC = Functional Component SFC = Stateless Functional Component
Type Type react.fc
= react.function.component
Sometimes it’s ok if you don’t, but the suggestion is to add it so you can tell Typescript about your function components
– jsDoc and interface
JsDoc is a plugin for adding formatting comments to func in the editor | IDE. It’s important to use the powerful VSCode Interface in Typescript. It describes my interfaces, objects…
The thing to note here is that jsDoc! == interface
- Mandatory => “:” The colon-marked attributes must exist. They cannot be more or less
- Optional attributes => “? “Optional” means optional
- Read-only attribute => “readonly” :
- Any attribute [propName: type] : any indicates that any attribute is defined as a string value
Interface is well written to make our code robust
– Generic and type
Take the following code for example
let _userList: Array<object> = []
let [userList, setUserList] = useState(_userList)
let _userList: object[] = []
let [userList, setUserList] = useState(_userList)
Copy the code
You can use either method, but don’t make them ===
Generics have even more powerful uses
function createArray<T> (length: number, value: T) :Array<any>...function createArray<T> (length: number, value: T) :Array<T> {
let result: T[] = [];
for (let i = 0; i < length; i++) {
result[i] = value;
}
return result;
}
createArray(3.'x'); // ['x', 'x', 'x']
Copy the code
– The union type and returns a value
function getLength(something: string | number) :number {
return something.length;
}
Copy the code
We should strictly follow this syntax to write ✍️ without returning void
– the plugin
Use ESlite to standardize the code we write
-
AlloyTeam ESLint
-
reference
-
Ps TS Quick reference table for error messages
Company project Private inconvenient to post code and project address