@ The author of this article ruoduan.cn reprint please indicate the source
-
origin
I will be fully responsible for the background management of IM instant chat, which will be added to the company’s mid-stage 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, I think it can replace mobx and Redux state management to some extent
- This article will cover Typescript, React-hook, and reacthook. TSX (practice)
- Typescript
- Project structures,
- The type definition
- Application analysis
- …
- Typescript
- react-hook ⭐️ - usestate-useeffect - useContext -... Redux, mobx, redux, React, redux, redux, redux, redux, redux, redux, redux, redux, redux, Redux, Redux, Redux, ReduxCopy the code
All right, let’s get started
Typescript
React-typescript project setup
The NODEJS environment requires a Not download link
We use the create-react-app scaffolding to build the React-typescript project environment directly
Version requirements NodeJS 8+, 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 typescript file definitions
// src. /react-app-env.d.ts // global declaration file tsconfig.json // typescript configuration fileCopy the code
Tsconfig. json 🌰
{"compilerOptions": {"experimentalDecorators": true, "target": "es5", // language compile 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 target directory "SRC",]}Copy the code
- React-app-env.d. ts is a TypeScript declaration file
🌰 such as:
You introducedjQuery
In the typescript:$('#dom'); // or jQuery('#dom'); Copy the code
// ERROR: Cannot find name ‘jQuery’. Error: 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 many library communities have already defined it for me. We just need to install it
yarn add @types/jquery --save-dev
We will also use the @types installation in later projects
You can search in TypeSearch for the library type you want
So far we’ve taken a look at Typescript’s project structure. As stated on its website, Typescript is a superset of JS, a progressive language that we can use directly to incorporate most of the new JS syntax and add types to it
Install antd, react-router-dom…
Yarn add antd react-router-dom 🌰
⚠️ : react-router-dom requires @types oh yarn add @types/react-router-dom –save-dev
Antd engineering reference
Let me step into the key ~
React-hook
React is divided into two components: a class component and a 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 life cycle
So in previous development, functional components were often supplemented as simple components
React-hook allows us to use state component state management in functional components, implement declaration cycles — side effects, and greatly simplify code, making it simpler and easier to understand
userState
Let’s look at the next two pieces of code
import React, { useState } from 'react'; Const [count, setCount] = useState(0); function Example() {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
- And you can see we’ve imported it
useState
Two variables are defined using array deconstruction syntaxcount, setCount
And we pass in an initial value of 0, and in the following use we get rid of the grossthis
You can use it directly - Conut is our hook variable equivalent to
state
- SetCount is what we’re targeting
count
The assignment function of phi is equal tothis.setState()
Effect Hook
Effect Hook allows 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); UseEffect (() => {title document.title = 'number ${count}'; }); Return (< div > < p > Numbers {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 = 'digit ${this.state.count}'; } componentDidUpdate() {document.title = 'digit ${this.state.count}'; } render() {return (<div> <p> number {this.state.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
-
A little bit of analysis: what are we using the data in the state of the class for?
-
We know that the data defined in state in the class component we will re-render the DOM tree after the data is updated
-
UseEffect is called after a DOM update has been performed. In this effect, we set the Document title property, but we can also perform data fetching or call other imperative apis.
- Note ⚠️ : By default, it is executed after the first render and after every update. (We’ll talk about how to control it later.)
-
What useEffect does is simply tell the React component to do something after rendering, UseEffect = componentDidMount (); useEffect = componentDidUpdate (); useEffect = componentDidMount (); useEffect = useEffect () They will determine the 'type' of the side effect according to the order of the 'return value' written in front of the useEffect and the destruction-return function: ### useEffect === componentDidMount 🌰 for example we want to request data when the page is mounted and render to the page let [list, SetList] = useEffect([]) // Get data const getList = async () => {let res = await axios(' XXX ')} // Side effect function mounted only once UseEffect (() => {getList()}, []) ### useEffect === componentDidUpdate 🌰Copy the code
let [list, setList] = useEffect([]) let [data, SetData] = useEffect(store.rows) const getList = async () => {let res = await axios(' XXX ') const getStore = () => { @observer let res = store.getxxxxx ... UseEffect (() => {getList()}, []) / / need to remove the side effects of function useEffect (() = > (() = > getStore) ())Copy the code
At this point we have a basic understanding of the use of reactHook. Basic 'Redux' is based on the previous useReducer, and the createContext. Const [state, dispatch] = useReducer(reducer, initialArg); It receives a Reducer of the form (state, action) => newState and returns the current state and its accompanying dispatch method. (Look familiar, you've used redux's children's shoes.)Copy the code
import * as React from 'react' const { useContext, useReducer, CreateContext} = React // Return status according to action.reduce function reducerInAction(state, Action) {if (typeof action.reducer == 'function') {return action.reducer(state)} return state} // Handle store data export default function createStore(params) { const { _State = {}, reducer } = { ... params, reducer: ReducerInAction} // Use createContext to manage state data distribution Let netxState = reducer(lastState, action) store._state = netxState return netxState } const store = { _state: _State, dispatch: undefined, getState: () => { return store._state }, useContext: () => {return useContext(Appcontext)}} // Const Provider => {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: Const Add_action = () => {return {type: 'ADD', reducer(state) {return {... state, age: state.age + 1 } } }Copy the code
Ps: The above is basic of Redux, but I still use MOBx in my actual project. Its design mode and object-oriented writing method are also more comfortable. May refer to
Practice (TSX + Hook)
– No decisionAny
– anyscript
Ps: Of course, this is not desirable, but in our rapid development process we sometimes have a generic | interface that is uncertain. We can temporarily use any first and then change it later
- Chestnut 🌰
For example, we want to pass an object to the subcomponent via props, but this object is interface data, and we are not sure about the data Type and properties of the object. We can use any instead.
– React.FC
We can see code like this:
const app: React.FC = () => {
...
}
Copy the code
FC = Functional Component SFC = Stateless Functional Component (deprecated)
FC
= react. FunctionComponent
In some cases, it’s ok if you don’t add it, so that you can tell Typescript about your function components
– jsDoc and interface
JsDoc is a plug-in that adds formatted comments to func in the editor | IDE. It’s important in Typescript that we use a powerful VScode interface that describes my interface, objects…
The one thing to note here is jsDoc! == interface
- Mandatory Attribute => “:” Attributes with colons (:) must exist, and cannot be more or less
- Optional properties => “? “Optional” means optional
- Read-only attribute => Readonly:
- Any attribute [propName: type] : any defines any attribute that takes a string value
Well written interfaces make our code very 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 you don’t code them
Generics have 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
– Union type and return 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 error information Quick reference list
Company project Private inconvenient to post code and project address