Preface:

As for why I want to write this article, on the one hand, I was inspired to read an article named “You know how to use ES6, then you should use it” a few days ago. Most of the things I said in the article are really experienced by me. Obviously I have learned some knowledge and skills, but I always can’t remember to use them in my work. On the other hand is the most recent resignation at home finishing your resume and what they have done over the past two years, so I want to share my personal feelings about my opinion of improving the quality of the code and practice, mainly from the Angle of conventional methods and recommended to obtain, analyze how to make our code looks more elegant, run up more excellent performance. The article is quite long, it is suggested to collect it slowly.

Note: the article about some knowledge points shared before, there are links to support, can reuse here will not repeat, because I do not want to make up the number of words and write, this is not my original intention. I share what I think is good to everyone, but also in this process to consolidate their knowledge of the knowledge, I hope this virtuous cycle will continue.

Code quality is a broad topic, and I’ll share it from three aspects (to be added later) :

1. Code refactoring;

2. ES6 (7, 8, 9, 10);

3. React optimization.

I. Code refactoring

Refactoring is probably one of the things people don’t want to do because it means reworking the code logic, the functional requirements, and the potential for delays. But I am feeling is we need to have a sense of incremental refactoring exist, if the current code has been far behind the existing technology, has been unable to tolerate or readability, so what are you waiting for, the best solution is to reconstruct, reconstruction can greatly improve the readability of the code, increasing the simplicity of the code, and more convenient maintenance.

1. Resource coordination before reconstruction

When we want to reconstruct, the first thing to consider is to make the business side aware of the necessity of the reconstruction, consult the remaining resources of each department, and persuade each department to participate in the front-end reconstruction.

Reasons for refactoring: frequent changes in requirements, urgent requirements reversal, simultaneous development without long-term planning direction, team code style differences, technology updates and iterations, etc.

The need for refactoring: Emphasized reconstruction technology of benefits and business benefits, provide the feasible reconstruction plan (including human resources, scheduling, scope changes, etc.), business letter, products, and the back-end, test, see the pain points and technical bottlenecks in the development, such as of the consequences that may not refactoring (update the limitations of iteration, the development progress of slow, troubleshoot problems difficult)

Benefits of refactoring: fewer bugs, lower maintenance costs, faster troubleshooting, faster development, etc

2. Refactoring steps

According to the scope involved in reconstruction, it can be divided into the following four scenarios:

A. Facelift (vue -> react);

As soon as I joined my second company, I took part in a big reconstruction, replacing the original old project vUE with React. We first set up the framework, and then made a prioritization of the various pages that need to be reconstructed. Design, front end, back end and testing were all involved. Most of the interfaces could still be reused, but the front end needed to be rewritten. The point here is to make sure old projects work, and that new features are tweaked as much as possible in new projects, prioritized, and migrated over time.

B. Normative reconstruction of code format (js -> ts);

The key point of this reconstruction is: first choose a target or a change direction, make sure that every change can run, after all, static check is not the function logic of the change itself, the probability of error is small, we can modify a small number of times.

C. Reconstruction of common components;

About the reconstruction of public components, should follow the principle of graceful degradation and progressive enhancement, if the current common components are dependent on less, the one-time can complete all update, but if it is using the high frequency component reconstruction may affect the broader extension, that need to be compatible with the old way do incremental updating reconstruction at the same time, the subsequent will gradually give up the old method during the revision.

D. Reconstruct specific functions.

Originally thought that text can express clearly, but when I write down, I find that drawing is more clear:

First check whether there are references by other components and dependencies. If there are, ensure that this reconstruction will not affect them. If there are no, sort out the current business, and synchronize the modification scope with the test and product (generally, if there are no back-end changes involved, notify the backend. In case of any problems, we need to consult the backend students) -> front-end development -> collaborative test to complete regression -> notify product acceptance -> notify the business side of changes, establish a wechat issue group of the enterprise, and ensure that there is any problem feedback at any time

3. Code modification rules

For code modification, you are advised to follow the following rules:

  • Single responsibility principle(SRP: Single responsibility principle)

Also known as the single function principle, object – oriented five basic principles (SOLID). It states that a class should have only one reason for change.

Name: Single responsibility principle

Single Responsibility Principle

There should never be more than one reason for a class to change. There should be one and only one reason for a class to change… It means that no matter what I do, I only do one thing. If you tell me to go grocery shopping, I only do grocery shopping. If you tell me to take out the garbage, I don’t do it

Temper: a word “ye”, two words “especially ye”

Partner: I have a single responsibility. Where can I find my partner?

Personal introduction: In this multi-responsibility society, I seem to be so maverick, but I do not know that a lot of things happening in the society are caused by the failure to deal with responsibilities, for example, often some parents with their children, while playing mobile phones, resulting in lost children, accidents and so on

In fact, it means that a method, a page component is best only one function or responsibility, as little as possible to coupling multiple functions in the same method, so for the later to find problems, reuse logic is a good habit.

Excerpt from Digger friend: LieBrother

  • Naming conventions

Naming conventions are commonplace, we often make fun of other people’s naming rules at the same time, we also need to pay attention to their own naming rules, like your wardrobe clothes, at a glance to be more uniform. Naming rule reference

  • The style is unified

Uniform code style, each of us has his or her own style of development, but in many cases, the code written by the same person will have multiple styles, which leads to the later maintenance of the code written by oneself is not easy to find problems. If the company team has norms, we try to comply with, or you think the company’s norms are not right, you can put forward, and then the team development as close as possible to it, so that we do not have too many complaints later maintenance, haha….

  • Duplicate code —Repeat Code

With regard to duplicate code I recommend that if there are more than one feature component at the page level, if there are more than three references to common components. We try to minimize repetitive code writing, which on the one hand wastes time and on the other hand is difficult to maintain. Of course, functional components and common components can also be differentiated and return different contents according to different parameters.

The last:

A final thought: When code smells bad, the first thing we do is flag it and schedule time to improve it. For example, you find that someone dug a hole in the wall you pass every day. After two days, you find that the hole is getting bigger and bigger, probably because you can take a shortcut through it. However, when more people walk, the hole is getting bigger and bigger, and the wall is becoming more and more dangerous, and there may be a landslide at any time. When we see this hole, can we think about it: since this shortcut brings convenience to everyone, can we inform the property management or neighborhood committee to remove this wall? If it’s a code problem, can’t be removed, or how to repair the wall? Instead of watching it get more dangerous every day. You know, no snowflake in an avalanche is innocent.

Second, the ES6

ES6 here is a broad concept, including but not limited to ES6, ES7, ES8, ES9, ES10, an overall concept. Today, I will share with you some common ES6 usage habits in my daily work. If there is any mistake, please correct me.

1. Variable definition:

The first is the definition of variables. Var is no longer used in the code. Instead, let and const are used, and most of them are const because of their differences 👇.

Let const var

  1. Let const is block-level scoped. Variables only apply to declared code blocks. Var does not.

  2. The var variable declaration is promoted to the head of the code block, which violates the rule of using variables first;

  3. Another reason is that the JS editor optimizes const to improve the efficiency of the program.

  4. A const declaration of a constant has two additional benefits. One is that readers of the code immediately realize that the value should not be changed, and the other is that it prevents errors caused by unintentional changes to the value of a variable.

  5. A const declaration must be assigned, only once. An object declared by const can change its properties;

  6. The let variable can be declared once and then assigned multiple times

Conclusion: From var to let const, this habit is to change their perception. See here if you’re already doing this, you’re great. If your mind is still stuck in the var era, it’s time to do a bit of research, because it’s a habit you need to develop in order to make your code more rigorous.

2. Default parameters:foo(a=1,b=2)=>{}

A function that takes a line argument, provides an initial value when the argument is missing or the value is undefined, and then determines whether to enable the default value depending on the case.

Missing:

Const foo = (name='xiaoqiu', age = 18) => {console.log(name,age)} // Default parameter value foo('zhangsan') // zhangsan 18 is automatically enabled when missingCopy the code

undefined:

Const foo = (name='xiaoqiu', age = 18) => {console.log(name,age)} // When the second parameter is undefined, it is identified as unassigned, The default parameter foo('zhangsan',undefined) // zhangsan 18 is automatically enabledCopy the code

null / fasle:

Const foo = (name='xiaoqiu', age = 18) => {console.log(name,age)} Foo ('zhangsan', NULL) // zhangsan null foo('zhangsan',false) // zhangsan falseCopy the code

3. Template string

Updated the way we use strings. Before template strings, we wanted to concatenate variables in strings that required ‘string’ + variable + ‘string’ to assemble, which was neither pretty to look at nor cumbersome to write. When we have template strings, variable concatenation is easy, and it is possible to make strings perform computations and functions.

Variable stitching

const name = `xiaoming`; const age = 18 ; Console. log(' My name is ${name},${age}. // My name is xiaoming,18.Copy the code

Line joining together

const a = `123 
    456`; 
console.log(a)

// 123
        // 456
Copy the code

Perform calculations

const x=10;
const y=100;

console.log(`a=${x-5},b=${x+y}`);  // x=5,y=110
Copy the code

Executive function

Function answer(){return "Today is Monday "; } console.log(' Me: What day is it today? ${answer()} '); Me: What day is today? // You: Just a moment, let me see. Today is MondayCopy the code

4. Deconstruct assignments

ES6 allows you to extract values from arrays and objects and assign values to variables in sequence according to a certain pattern. This is called deconstruction. The concept is abstract, and the following is illustrated with practical examples.

Union declarations with arrays:

const [a, b, c] = [1, 2, 3]; 
Copy the code

Array deconstruction:

const [x, y, z] = [1, 2, 3];

x // 1
y // 2
z // 3
Copy the code

Array deconstruction — assignment of remaining arguments:

const [x, y, ...z] = [1, 2, 3, 4, 5];

x // 1
y // 2
z // 3,4,5
Copy the code

Json data deconstruction:

const obj = { a: 'haha', b: 'gaga' ,c: 'guagua'};
const {a, b, c} =obj; 

a // haha
b // gaga
c // guagua
Copy the code

Complex JSON data deconstruction:

let node = { type: "Identifier", name: "foo", obj: { start: { line: 1, column: 1 }, end: { line: 1, column: 4 } } }; Node.obj. start let {obj: {start: localStart}} = node; console.log(localStart.line); // 1 console.log(localStart.column); / / 1Copy the code

String deconstruction:

const [a, b, c, d, e] = 'hello';

a // "h"
b // "e"
c // "l"
d // "l"
e // "o"
Copy the code

Function argument deconstruction:

function add([x, y]){ return x + y; } add([1, 2]); / / 3Copy the code

Destruct the return value of a function directly:

function example() {
  return [1, 2, 3];
}

const [a, b, c] = example();
Copy the code

Swap variable values:

const a = 1;
const b = 2;

[a, b] = [b, a];
Copy the code

Module specified method destruct:

import { useRequest } from 'ahooks';
Copy the code

There are a lot of scenarios for deconstructing assignment. The above is just a list of my common ones. Welcome to add!

5. Arrow function

ES6 allows the use of “arrows” (=>) to define functions. Delete the function keyword and function name from the original function and use => to concatenate the argument list with the function body. It doesn’t have its own this, arguments, super or new.target.

Arrow functions are different from normal functions

  1. In vivo functionthisObject is the object at which you define it, not the object at which you use it. Arrow functions cannot be modified directlythisPoint;
  2. Cannot be used as constructors, that is, not usednewCommand, otherwise an error will be reported;
  3. UnusableargumentsObject that does not exist in the function body. You can use it if you wantrestParameter substitution;
  4. UnusableyieldCommand, so the arrow function cannot be usedGeneratorFunctions;
  5. Arrow functions do not support renaming function arguments.

The arrow function this points to:

  1. Ordinary functionalthisObject pointing is mutable, but in the arrow functionthisIs fixed, the actual reason is that the arrow function doesn’t have its ownthisLead to internalthisThat’s the outer code blockthis ï¼›
  2. Arrow functionthisRefers to the parent scopethis, is determined by looking at the scope chainthisThat is, it points to the object on which it is defined, not the object on which it is used; A normal function points to its direct caller;
  3. The arrow function has no normal function outside, in strict mode and in non-strict modethisLeads towindowGlobal object.

Writing style:

// const f = function (a) {return a; }; // arrow function const f = a => a; Const f = () => {return "1"}; // Const f = () => {return "1"};Copy the code

Use REST instead of arguments

const numbers = (... nums) => nums; numbers(1, 2, 3, 4, 5)Copy the code

6. Operator extension

Operators perform program code operations on more than one operand item. Here’s a rundown of the various es6 operators, the last one I haven’t used before: 🤔

Extended operators…

The spread operator is three points… , which is like the inverse of the REST argument, turns an array into a comma-separated sequence of arguments that can only be placed in the last bit of the argument when placed in an array.

Expand values, unbracket arrays, merge arrays, :

console.log(... [1, 2, 3]) // 1 2 3 console.log(1, ... [2, 3, 4], 5) // 1 2 3 4 5 console.log([ 1, ...[2, 3, 4], 5 ]) // [1, 2, 3, 4, 5]Copy the code

Merger Statement:

const [first, ...rest] = [1, 2, 3, 4, 5];  

console.log(rest)  // [2, 3, 4, 5]
Copy the code

Merge arrays/objects:

,4,7,9 const a = [2] / / ES5 [1, 2] concat (a) / / [1, 2, 2, 4, 7, 9] / / ES6 [1, 2,... a] / [1, 2, 2, 4, 7, 9]Copy the code

String extensions to arrays:

[...'happy']  

// [ "h", "a", "p", "p", "y" ]  
Copy the code

Expand the objects of the Iterator interface:

The extension operator internally calls the Iterator interface of the data structure, so it can be used by any object that has an Iterator interface.

let map = new Map([  
[1, 'one'],  
[2, 'two'],  
[3, 'three'],  
]); 

[...map.keys()];     // [1, 2, 3]
[...map.values()];   // ['one', 'two', 'three']
Copy the code

Arrays and object copies:

You can also copy objects using extension operators, which we shared earlier, and here’s the portal

With the new Set array to deduplicate:

const arr = [1, 2, 1, 2, 6, 3, 5, 69, 66, 7, 2, 1, 4, 3, 6, 8, 9663, 8];
 
console.log([...new Set(arr)]);  // [1, 2, 6, 3, 5, 69, 66, 7, 4, 8, 9663]
Copy the code

Optional chain? .

The optional chain operator (? .) allows you to read the value of a property located deep in the chain of connected objects without explicitly validating that each reference in the chain is valid. ? The. Operator functions like the. Chain operator, except that it does not cause errors when references are nullish (null or undefined), and the short-circuit returns undefined. ? The. Operator acts as a short-circuit mechanism that stops executing if the condition is not met.

When we have a variable message and we want to get the value of one of its nodes, the old way of doing this is to make sure that we don’t get an error, layer by layer

// ES5:
const firstName = (message
  && message.body
  && message.body.user
  && message.body.user.firstName) || 'default';

Copy the code

Now, what do you do, just use the chain call, check? Does the preceding content exist in the upper object of the property, whether it is null or undefined, return undefined if it does not exist, if it does exist, continue to call backwards, then message? .body is equivalent to message.body, simplifying writing.

// ES6: const firstName = message? .body? .user? .firstNameCopy the code

When used with a function call, returns undefined if the given function does not exist.

onCancel={() => { setVisible(false); onClosed? . (); }}Copy the code

Null-value merge operator??

Null-value merge operator (??) Is a logical operator that returns the right-hand operand if the left-hand operand is null or undefined, otherwise returns the left-hand operand.

const foo = null ?? 'default string'; console.log(foo); // "default string" const baz = 0 ?? 42. console.log(baz); / / 0Copy the code

Exclude non-null and undefined false values:

In this line of code, we want to use the default value of undefined/null on the right side, but in fact, if the left side of the input parameter is false, 0, ‘ ‘, it will return the default value of the right side, which is a bit contrary

ES5: const okText = props? .buttonProps? .loading || false;Copy the code

With the optional chain operator setting the default value, we can do what we need

ES6: const okText = props? .buttonProps? .loading ?? falseCopy the code

Logical operator

Es6 new logical operators | | =, && =?? =, these three operators are equivalent to performing the logical operation first, then performing the assignment based on the result of the operation, and then depending on the situation.

And (OR) logical operators | | =

Logical OR assignment (x | | = y) operator only in x is falsy value assignment.

const b = { a : 2 } ; / / b.a left back 2, not false, the results back 2 b.a | | = 4; console.log(b.a) ; / / 2 / / b.d prototype chain was not found on the left side of the b d, returns false, assign a value to the right, the result b.d assignment of 8 b.d | | = 8; console.log(b.d) ; // 8 b.c = 23 console.log(b) ; // {a: 2, d: 8, c: 23}Copy the code

Set default values for property values:

// ES5
user.age = user.age || 18;

// ES6
user.age ||= 18;
Copy the code
Logic (ANDThe assignment operator &&=

The logical AND assignment (x &&= y) operator only assigns if x is true.

let a = 1; let b = 0; // the left side of the operator is true and returns 2 a &&= 2; console.log(a); // the operator is false on the left and does not assign b &&= 2; console.log(b); / / 0Copy the code
Logical null assignment?? =

The logical null assignment operator (x?? = y) only if x is nullish (null or undefined).

Did we just learn one above? And now this…? What’s the difference between lambda and this? The main difference is…? = is assignment,?? Just judge logic, above example 🌰 :

Const a = {b: 2, c: 0, d: false}; / / use?? To determine that the result is not assigned to a.e. A.E?? 99; console.log(a.e) ; // undefined // requires a separate declaration and assignment, so?? Const l = a.e?? 99 console.log(l) // =, the result is an a.f?? That can be added to the a object. = 100; console.log(a) ; // {b: 2, c: 0, d: false, f: 100} console.log(a) ; // {b: 2, c: 0, d: false, f: 100, ee: null} ;Copy the code

Assign an attribute value to a parameter:

// Old method: function example(params) {function example(params) {params? .loading = params? .loading ?? false (params? .okText) ?? Function example(params) {function example(params) {function example(params)? .loading ?? = false params? .okText ?? = 'confirm'}Copy the code

Exponentiation operator **

The exponentiation operator (**) returns the result of adding the first operand to the power of the second. It is equivalent to math.pow, except that it also accepts BigInts as its operand.

Math.pow(3,4) // 81 console.log(3 ** 4); // 81 console.log(10 ** -2); // 0.01 console.log(2 ** 3 ** 2); // 512 console.log((2 ** 3) ** 2); / / 64Copy the code

7. Extensions to array methods:

For the array operations, we can combine the previously shared array methods to see, next we will analyze the new array operations on ES6:

Array.of()Creating an array instance

The array.of () method creates a new Array instance with a variable number of arguments, regardless of the number or type of arguments.

Array.of() and Array:

The difference is in the handling of integer arguments: array.of (7)**** creates an Array with a single element 7, while Array(7) creates an empty Array of length 7 (note: this is an Array with seven empty Spaces, not an Array with seven undefined).

Array.of(7)   // [7]

new Array(7)  // [empty × 7]
Copy the code

Array uncertainty

Array() // [] Array(3) // [empty × 3] Array(3, 11, 8) // [3, 11, 8]Copy the code

Determinism of array.of

/ / regardless of the number of parameters. The returned Array is an Array of () / / [] Array of (3) / / [3] Array) of (3, 11, 8) / / [8] 3, 11,Copy the code

To convert a set of values to an array:

Array. Of (1,2,3) // [1, 2,3] Array. Of (1,2,3) // [1, 2,3] Array.Copy the code
Includes determines whether an array contains a specified value

The includes() method is used to determine whether an array contains a specified value, returning true if it does and false otherwise. This method is very similar to the one we are familiar with, indexOf, but indexOf returns -1 instead of a Boolean value of true/false, which is a little less elegant in determining the result.

const array1 = [1, 2, 3];
console.log(array1.includes(2));    //  true

const pets = ['cat', 'dog', 'bat'];

console.log(pets.includes('cat'));  //  true

console.log(pets.includes('do'));   //  false

[1, 2, NaN].includes(NaN); // true
Copy the code
Array.fromCreating a new array

The array.from () method creates a new, shallow-copy Array instance from an array-like or iterable. This method was shared in the original Array method collation, linked here to array.from

find() 和 findIndex()Finds the value of a compound condition on an array

The find() method returns the value of the first element in the array that satisfies the provided test function. Otherwise return [undefined]

Example find

The findIndex() method is similar to find in that it looks for the first element but returns the index of the first element in the array that satisfies the provided test function. Returns -1 if no corresponding element is found

const array1 = [5, 12, 8, 130, 44]; const isLargeNumber = (element) => element > 13; console.log(array1.findIndex(isLargeNumber)); / / 3Copy the code
fill()Fill the array

The fill() method fills all elements of an array from the start index to the end index with a fixed value. Does not include terminating indexes.

You can accept up to 3 parameters: arr.fill(the value to be filled, the start of the fill, and the end of the fill)

const array1 = [1, 2, 3, 4]; Log (array1.fill(6)); console.log(array1.fill(6)); Log (array1.fill(5, 1)); Console. log(array1.fill(0, 2, 4)); console.log(array1.fill(0, 2, 4)); // [1, 2, 0, 0]Copy the code
copyWithinCopy the array

The copyWithin() method shallowly copies part of the array to another location in the same array and returns it without changing the length of the array.

You can accept up to 3 arguments: arr.copywithin (the starting position of the replacement, the beginning position of the replacement, and the end position of the replacement in the old array)

const array1 = ['a', 'b', 'c', 'd', 'e'];

Copy the code
console.log(array1.copyWithin(0, 3, 4));  

//  ["d", "b", "c", "d", "e"]
Copy the code

👆 since the location of the index of 0 are covered, the index of 0 is’ a ‘, starting from the index position of the 3 assignment, index 3 position is’ d ‘, then the array is a ‘d’ 0, to the end of the index for 4 place, including index in front of the position, the final index does not include the location, that is the copy one, the rest of the default pad: [‘d’, “b”, “c”, “d”, “e”]

console.log(array1.copyWithin(1, 3));    

//  ["d", "d", "e", "d", "e"]
Copy the code

👆 this method changes the original array, at which point our copy of the original array becomes the return value above: [“d”, “b”, “c”, “d”, “e”]. [‘d’,’d’,’e’], “d”, “e”, “d”, “e”, “d”, “e”, “d”, “e”]

Conclusion: When I first came into contact with this method, I felt it was not easy to understand, thinking: Who would use such a difficult to understand the method to operate the array, re-declare an array is not very convenient, copy to copy is not enough trouble, so that the back will never use, today again look is also a reasonable next to remember, so write a lot of description, I hope to help you. As for the use of scenarios, you can use them in some word games, or in games such as pushing boxes, other scenarios are still to be explored, if you know of other scenarios, please leave a comment to me at 👇.

flat().flatMap()Array flattening

The Flat () method recurses through the array of numbers at a specified depth and returns all the elements in a new array combined with the elements in the traversed subarray. Refer to the flat of the original array method

aboutES6Void of array in:

The vacancy of an array

8. String extensions:

For other string methods, see here, but only the most recent ones in ES6

trimStart 和 trimEndDelete before and after whitespace, does not affect the original array

The trimStart() method removes whitespace from the beginning of the string. TrimLeft () is an alias for this method.

const greeting = '   Hello world!   ';

console.log(greeting.trimStart());  // 'Hello world!   ';

console.log(greeting.trimLeft());   // 'Hello world!   '
Copy the code

The trimEnd() method removes whitespace characters from the end of a string. TrimRight () is an alias for this method.

const greeting = ' Hello world! '; console.log(greeting.trimEnd()); // " Hello world!" ; console.log(greeting.trimRight()); // " Hello world!" ;Copy the code

For more regular methods to remove whitespace, see here

PadStart and padEnd fill strings

The padStart() method populates the current string with another string (repeated multiple times if necessary) so that the resulting string reaches the given length. PadEnd () is used for tail completion.

'x'.padStart(5, 'ab') // 'ababx'
'x'.padStart(4, 'ab') // 'abax'

'x'.padEnd(5, 'ab') // 'xabab'
'x'.padEnd(4, 'ab') // 'xaba'
Copy the code

9. Promise. All ([a, b]), execute multiple promises simultaneously

The promise.all () method is used to wrap multiple Promise instances into a new Promise instance. The Promise’s resolve callback is executed when all the incoming Promise’s resolve callbacks have ended, or when no promises are left in the input iterable. Its Reject callback execution throws an error as soon as any incoming promise’s Reject callback is executed or an invalid promise is entered, and reject is the first error message thrown.

const p = Promise.all([p1, p2, p3]);
Copy the code

The state of P is determined by P1, P2 and P3, which can be divided into two cases.

(1) Only when the states of P1, P2 and P3 become depressing, the state of P will become depressing. At this time, the return values of P1, P2 and P3 will form an array and be passed to the callback function of P.

(2) As long as p1, P2 and P3 are rejected, P becomes rejected, and the return value of the first rejected instance is passed to p’s callback function.

Promise.all([... formlist.map (item => item.validateFields())), validateFields()]).then(data => { ... dosomething });Copy the code

Third, the React

In this session, we’ll share some of the elegant writing styles and methods in the React framework, as well as the different uses of similar methods and performance improvements.

Note: HERE I assume you are already familiar withreactFramework and understand its basic use, if not too familiar with, aboutreactI published an article in the past,You can see here

Below I will use the form of question and answer to share, about inreactHow to better improve performance optimization and improve work efficiency.

About 1.vue 和 react

The discussion about VUE and React has always been the focus of public opinion. Although an unnamed bigwig said: The current situation is that generally large companies use React more, while small companies use VUE more, there is no absolute opinion on which is better, and it is all relative. My personal opinion is as follows: Whichever is comfortable to use is fine. Here are the obvious differences I feel.

Differences in writing styles:

Vue:

Vue recommends the single file component format of Webpack + VUe-Loader. Vue retains the separate writing method of HTML, CSS and JS, so that the existing front-end developers can keep their original habits when developing, which is closer to the common Web development mode. The template is ordinary HTML. Mustache is used for data binding and CSS is used directly for styling. The

react:

React is a rendering function that returns a virtual DOM tree. React recommends JSX + inline style, which translates HTML and CSS into JavaScript: ‘all in JS ‘. JSX is really a set of syntactic sugar that uses XML syntax to make it easier to describe tree structures. In React, all components rely on JSX for rendering. You can write xmL-like syntax in Render (), which will eventually be compiled into native JavaScript. Not only can HTML be expressed in JSX, but the trend is to incorporate CSS into JavaScript as well. JSX is a set of additional grammars based on JS that can be learned and used at a cost.

About data binding:

Vue:

It is known for two-way data binding, but also one-way data flow. Why? In fact, the two do not conflict. One-way data flow means that data flows in a single direction, that is, from the parent component to the child component. When the child component receives the data from the parent component, it cannot modify the data of the parent component.

Data flow:

Graph TD parent --> child component

What about two-way data binding? The key to bidirectional binding is how data updates the view, because a view updates data by listening for events, such as input tags listening for ‘input’ events. So let’s focus on how we update the view when the data changes. The focus of the data update view is how to know that the data has changed, and once you know that the data has changed, then everything else is easy to deal with. DefineProperty () sets a set function on the property. This function is triggered when the data changes, so we can update the view by putting in some methods that need to be updated.

react:

React is also a one-way data stream, but the data binding is one-way. Instead of changing state directly, use setState to change data. It doesn’t take effect immediately, it’s asynchronous. So don’t assume you can get the latest value immediately after calling setState. Sequential setStates are not executed synchronously one after the other, but are added to an asynchronous queue and then finally executed together, i.e., batch processing. React’s data manipulation is clearer than vUE’s two-way binding.

Conclusion: Each company has its own choice as to whether to use VUE or React. No matter which one is born to improve our work efficiency, each one has its own advantages and disadvantages, which will not be elaborated here. I have used Vue and React. Most of vue’s community is run by the author You Yuxi or his team. The surrounding methods are officially recommended and a series of apis are provided. The React JS library was created by Facebook and has a large number of contributors as well as a large community of developers who contribute their solutions to various problems. The community is quite active and flexible.

2. umi:ReactA one-stop build tool

This is a one-stop build tool right out of the box that includes the tools necessary for our development process, we just need to care about the business, and it takes care of the rest. Webpack + webpack-dev-server + Babel + postcss +… The react-router router is used for routing.

👆 This is how it was used in the previous generation. Tools are tools and libraries are libraries. More recently, we’ve found that tools and libraries can be mixed together, and tools are part of the framework. Reduce the amount of code developers need to write by facilitating development through conventions, automatic generation and parsing of code. Interfaces are the New Frameworks.

Umi website

Umi document

3.Mobx or Redux ?

Mobx is a powerful, easy-to-use state management tool. Even the authors of Redux have recommended it, and in many cases you can use Mobx instead of Redux.

Add in the...Copy the code

Redux is a JavaScript state container that provides predictable state management

Add in the...Copy the code

Mobx official documentation redux

4. Egg.js

Egg.js is an enterprise application framework of Ali based on NODEJS and KOA2, based on ES6, ES7 and NodeJS. For a beginner’s guide to Node, see here

Add in the...Copy the code

An Egg. Js’s official website

An Egg. Js document

React + Typescript

Ts is js in strict mode, so to speak, and the more code we write, the more we understand how important rules are. Ts is under the condition of without changing the original js written on it to add static type checking, we don’t have to worry about taking over the project document, no comment, now have a ts, type system in fact is the best document, direct and clear labelling: what is required, which is optional, as well as the specific data type is clear.

React cooperated with the practice of TS, so it was really necessary to write. It not only strictly required ourselves, but also unified our writing habits, so that the overall code would be very clear whether we read the code by ourselves or entrusted to other students for maintenance.

Typescript practices and React with typescript practices

6. Use the right Ant Design Pro tool to double the efficiency

Ant Design Pro is based on Ant Design and UMI’s packaging of a set of enterprise-level back-end front-end/Design solutions, committed to the Design specifications and basic components, continue to build up, extract typical templates/business components/supporting Design resources. To further improve the experience of “users” and “designers” in the design and development process of enterprise-level background products.

Ant Design Pro strives to provide an out-of-the-box development experience by providing a complete scaffolding for internationalization, permissions, mocks, data flows, network requests, and more. Best practices are provided to reduce learning and development costs for these common scenarios in the middle and back end.

At the same time, in order to provide more efficient development experience, provides a series of template components, ProLayout, ProTable, ProList are a good helper in the development of background, can significantly reduce the sample code.

You can see the entire Ant Design Pro architecture in the larger image at 👇 below.

Ant Design Pro website

Ant Design Pro documentation

7. A library of productivity toolsahooks

Ahooks is a React Hooks library dedicated to providing frequent, high-quality Hooks. The React function is a library that contains some of the most common functions and methods, as well as methods that are reacted on the react function to make it more relevant to the needs of the business

Introduction and use are also extremely concise:

import React from "react";
import { useToggle } from "ahooks";


export default () => {
  const [ state, { toggle } ] = useToggle();


  return (
    <div>
      <p>Current Boolean: {String(state)}</p>
      <p>
        <button onClick={() => toggle()}>Toggle</button>
      </p>
    </div>
  );
};
Copy the code

About ahooks official website

8. React çš„ HooksCompared to the componentClassWhat are the advantages and disadvantages of class components

Class component, an HTML component returned by Render. Class components have not only State, but also a life cycle. Each instance of a component, from creation, to execution, to destruction, emits a series of events called component lifecycle functions.

Here are the class class components

import { PureComponent } from "react"; class Parent extends PureComponent { constructor(props) { super(props); this.state = { id: 1 }; } render() {return (<div>); } } export default Parent;Copy the code

Hook is a new feature in React 16.8. It lets you use state and other React features without having to write a class. Not only is it simple to write, but you don’t have to worry about this anymore.

The following ishooksFunction component

import React from 'react'; import { Button } from 'antd'; Const App = () => {const handleClick = () => {console.log(' button click '); }; <Button onClick={handleClick}> Button </Button>; }; export default App;Copy the code

On the difference between the two:

  1. It’s written as the largest,HooksIt’s much cleaner, it just returns a function body;classThe component requires a constructorconstructorAnd the needrender returnahtmlBody.
  2. The second is aboutthisPoint to the problem inclassWithin the component, we use state and add events with this in mindhooksThere are no such considerations at all.
  3. And then there’s the classification of the life cycle inclasWe can get a lot of life cycles,Look here, we can do corresponding operations in different stages, inhooksBy incorporating most of the life cycle, we can almostuseEffectDo most of the operations in.

As we get more used to using hooks, go back to the class component and see that classes are bloated, like one in summer and one in winter, and we can do the same thing in a much more elegant way with less code, so why not?

Here is the official advice on whether the two methods should be unified

9. Select and use according to the scenariouseStateoruseReducer

We all know that useState and useReducer can be used to store state, so what is the difference? Look here

10. setStateIs it synchronous or asynchronous? whensetStateWhen the same reference is returned,renderWill it be implemented?

SetState is executed asynchronously. We all know that react doesn’t allow you to change the value of state directly. We need to use setState to change data, and it doesn’t take effect immediately. It’s asynchronous. So don’t assume you can get the latest value immediately after calling setState. Sequential setStates are not executed synchronously one after the other, but are added to an asynchronous queue and then finally executed together, i.e., batch processing.

Render does not execute when setState returns the same reference, as in the following example:

import { PureComponent } from "react"; import { Button } from "antd"; class Workplace extends PureComponent { constructor(props) { super(props); this.state = { a: 1 }; } action = {handleParams: () => {// When 'setState 'performs the same assignment as the initial value: this.setState({a: 1}) console.log('setState performed ')}}; Render () {return (<div> <h1> worktable </h1> <Button onClick={this.action.handleParams}> {console.log('render executed ')} </div>); } } export default Workplace;Copy the code

First render is executed, which is a must, then we click the button, execute setState, and look at the console output, there is no second render:

Now I will change this. When the button is clicked, I will change the value of a to 3 and leave the rest unchanged as above:

HandleParams: () => {this.setState({a: 3}) console.log('setState executed ')}Copy the code

Now look at the result returned from the console:

Compared to the last operation, this time returns a render print, that is, when setState returns the same reference, the render will not be triggered. The react diff algorithm determines that when two values are the same, the render will not continue down.

About diff algorithm:

React Diff compares old and new nodes layer by layer from the Root node of the Fiber tree. The component’s key and type determine whether the old node needs to be reused. The node’s index ultimately determines whether the DOM needs to be moved. Nodes that are not being reused are removed, so there is no need for diff of the subtree, and therefore no need for cross-level diff.

Compare different types of elements:

When the root node has a different type of element, React disassembles the existing tree and creates a new one. For example, when an element changes from to , from

to

, or from


Compare elements of the same type:

When comparing two React elements of the same type, React preserves the DOM node and only compares and updates the changed attributes.

<div className="before" title="stuff" />

<div className="after" title="stuff" />
Copy the code

By comparing the two elements, React knows that it only needs to change the className attribute on the DOM element.

Recurse on child nodes:

By default, React iterates through lists of both child elements at the same time when recursing to the child elements of a DOM node

<ul>
  <li>first</li>
  <li>second</li>
</ul>

<ul>
  <li>first</li>
  <li>second</li>
  <li>third</li>
</ul>
Copy the code

React matches two

  • first
  • trees, then matches the second< li>second tree, and finally inserts the

  • third
  • tree of the third element.


    Recommended articles:

    Diff algorithm (Mom doesn’t worry about my Diff interviews anymore)

    React diff

    Of course, if you really need to get the assigned value, you can use setTimout to get it, as follows:

    ChangeText () {setTimeout(() => {this.setState({message: "I am a new message"}); console.log(this.state.message); // I am new message}, 0); }Copy the code

    11. useCallback,useMemo,useEffectThe difference between?

    Common: Both update only when a dependency changes;

    The difference is that useMemo is a cache variable, useCallback is a cache callback function, and useEffect is delayed until the browser finishes rendering the screen, regardless of whether the parameter is monitored, and is updated when the dependency changes.

    The listening process for each method?

    Both use the second argument of the function to do dependency collection and then listen for changes to the second argument to determine whether to re-render. Whenever a change occurs, get the latest value, update the function/variable in the cache, etc. Here’s an example of useMemo:

    Before using useMemo:

    import React, { useState } from 'react'; const App = () => { const [count, setCount] = useState(0); const userInfo = { name: "Jace", age: count }; Return <div> name: {userinfo.name}</div>} export default AppCopy the code

    Using useMemo:

    import React, { useState, useMemo } from 'react'; const App = () => { const [count, setCount] = useState(0); const userInfo = useMemo(() => { return { name: "Jace", age: count }; }, [count]); Return <div> name: {userinfo.name}</div>} export default AppCopy the code

    Obviously the above userInfo will be a new object each time and will cause the component to re-render whether the count changes or not, whereas the lower one will return the new object only after the count changes.

    useEffectthereturnWhen will it be implemented?

    UseEffect returns a function that executes something when a component is destroyed, so that the contents of the return function are executed when the component is destroyed:

    useEffect(() => { handelColumns(tabVal || 'intention'); // it needs to be a function. Return () => {// Console.log (1) will only be executed on destruction; }; } []);Copy the code

    So when we use it, we can choose the right one according to its function.

    12. Higher-order functions

    HOC is an advanced technique used in React to reuse component logic. HOC itself is not part of the React API; it is a design pattern based on the composite features of React. Higher-order functions are used to strengthen components, reuse logic, improve rendering performance, etc.

    As for higher-order functions, my understanding is not profound, and I will share it with you when MY wings are rich. I recommend reading this article

    13. The customhooks

    A custom Hook is a function whose name starts with “use” that can call other hooks from within. Here is an example of the custom hooks shared earlier

    14. What data changes trigger rerendering?

    Normal rendering of components is a must, but when unnecessary rendering occurs, it can be costly to performance on the one hand, and can cause the user to feel like the page is stuck on the other. So what data changes trigger rendering?

    1. Component statestateThe value of is changed, which is triggeredsetStateMethod, which triggers rendering by default. Of course, there are special cases: whensetStateDoes not fire when the same reference is returnedrender;
    2. The father of the componentpropsAfter being modified, all child components are also re-rendered by default;
    3. Of the child componentstateState changes do not affect the parent, and the parent does not re-render;

    15. Performance optimization, how to avoid unnecessary rendering?

    In React, we learned that when you update a component, it triggers all the child components to update. The entire component tree is rerendered in turn, which means that every change in the APP causes the entire APP to be rerendered. Even though React doesn’t actually change the DOM, it evaluates the VDOM and makes comparisons. That’s a lot of work, and you’ll see the entire UI slow down, especially in a large application. This is one reason why the React component requires immutability. In our actual development process, we need to determine whether to load on demand according to different scenarios. The following is a look respectively, and then we can choose according to their own needs:

    React.lazyIt is not loaded the first time, and then loaded when the dependency is modified

    The react. lazy function allows you to render dynamically imported components in the same way as regular components. React.lazy is used for not loading the file for the first time and then loading it when there is an update. For details, see here

    React.MemoThe first load, there are changes will be updated, otherwise do not re-render

    If your component is rendering the same props, you can improve the performance of the component by wrapping it in a react.Memo call to remember the component’s rendering results. This means that in this case React will skip the render component and simply reuse the results of the last render. React.memo only checks the props changes. If the function component is wrapped in react. Memo and its implementation has useState, useReducer, or useContext hooks, it will still re-render when state or context changes. For details, see here

    shouldComponentUpdate

    Check whether the output of the React component is affected by changes to the current state or props based on the return value of shouldComponentUpdate(). ShouldComponentUpdate () is called before rendering when props or state changes. The default return value is true. Do not attempt to rely on this method to “block” rendering, as this can be buggy. In most cases, you can inherit react.pureComponent instead of shouldComponentUpdate(). It overrides the implementation of shouldComponentUpdate() with a shallow comparison of the current and previous props and state.

    ShouldComponentUpdate (nextProps, nextState) {// Render return true; }Copy the code

    React.PureComponent

    Like React.Memo, the PureComponent makes a shallow comparison between props and state and reduces the possibility of skipping necessary updates. , but react. PureComponent applies to class components, not function components.

    React.componentwe all know that react.componentis the base class that defines the React component using ES6 classes:

    class Greeting extends React.Component { render() { return <h1>Hello, {this.props.name}</h1>; }}Copy the code

    React.PureComponent is very similar to react.component.react.component.react.pureComponent. The difference is that shouldComponentUpdate() is not implemented in react.pureComponent, which is implemented in a shallow way to compare prop and state. If the object contains complex data structures, it is possible to produce incorrect alignment results because deep differences cannot be examined. Here is an example of a PureComponent:

    The parent component:

    import React, { PureComponent } from "react"; import { Button } from "antd"; import Child from "./child"; class Analysis extends PureComponent { constructor(props) { super(props); this.state = { b: 1 }; } action = { handleParams: () => { this.setState({b:2}) } }; Render () {return (<div> <h1> <Button onClick={this.action.handleparams}>handleParams</Button> {the console. The log (' parent component rendering ')} < div > Child components: < Child / > < / div > < / div >). } } export default Analysis;Copy the code

    Child components:

    import { PureComponent } from "react"; class Child extends PureComponent { constructor(props) { super(props); } to render () {return (< div > < h1 > child - page < / h1 > {the console. The log (' child components to render ')} < / div >). } } export default Child;Copy the code

    When we update the props of the parent component, the console does not output a rendering of the child component because the child component is not using the props of the parent component, thus reducing unnecessary rendering.


    This article is not over yet, I hope I can continue to update, if you are reading this article any questions 🤔, feel free to leave a comment.


    If the pro feel my article is good, you can add attention to oh!

    Content is still in the continuous update, afraid of missing the update of a focus on bai! Point a concern not to get lost oh! 😄

    Please push

    Note: If you have a partner company looking for a job, please contact me! React, TS, ANTD, Webpack… Please refer to my article. Location: Beijing, Tel: 15210667658