in the previous two articles, we analyzed the implementation, mounting, and lifecycle processes of React components. In reading the source code, we often see code such as transaction and UpdateQueue , which involves two concepts in React: transactions and update queues. Because we have covered all of these in the previous article, this article explores the transaction mechanism and update queues based on the all-familiar setState method. 1.setState related in the first article Analysis of React Source Code (1): implementation and mounting of components we already know The component prototype declared by class has the setState method: this method passes in two parameters partialState and callBack , the former is the new state value, and the latter is the callback function. updater is defined in the constructor: you can see that updater is passed in by the constructor, so if you find out where new ReactComponent is executed, you can find out what updater is. Taking the custom component ReactCompositeComponent as an example, we found its trail in the _ constructComponentWithoutOwner method: return new Component(publicProps, publicContext, updateQueue); undefined the corresponding parameter updater is actually updateQueue . Let's look at what enqueueSetState is in this.updater.enqueueSetState : The purpose of the getInternalInstanceReadyForUpdate method is to get the current component object and assign it to the internalInstance variable. Next, determine whether the state update queue for the current component object exists, and if so, add the partialState , that is, the new state value, to the queue; if not, create an update queue for the object, and notice that the queue exists as…

April 11, 2023 0comments 1444hotness 0likes Aaron Read all

in the previous article "React source code parsing (1): component implementation and mounting , we described the implementation and mounting of React components. Now let's explore the life cycle of components. We already know that the lifecycle of the component will be triggered only after the mount process starts, and a js object of type ReactElement will be generated. By parsing the information contained in the component object, the corresponding HTML information is obtained, inserted into the specified DOM container, and the rendering of the view is finally completed. So how is the life cycle of the component triggered in this process? in fact, the study of the declaration cycle of components is a more in-depth study of the mounting process of components. Lifecycle of components at the end of the previous article, we know that the ReactDOM.render () method internally generates four different types of wrapper components through the factory method, depending on the parameters passed in: ReactEmptyComponent ReactTextComponent ReactDOMComponent ReactCompositeComponent when executing the mount process, the lifecycle is triggered by executing mountComponent methods within each encapsulated component, but it is clear that the lifecycle exists only in the React custom component, that is, ReactCompositeComponent . Because the other three components do not have a lifecycle, let's first analyze the relatively easy three internal components that do not exist lifecycle. 1.ReactEmptyComponent is created by the ReactEmptyComponent.create () method, which finally calls the ReactDOMEmptyComponent method. Take a look at the source code: because the component is empty, almost all parameters are set to null and have nothing to do with…

April 10, 2023 0comments 1303hotness 0likes Aaron Read all

when we are proficient in using React for front-end development, we will inevitably have a strong interest in the internal mechanism of React. What are the components? Is it the real DOM? What is the basis for the execution of lifecycle functions? in this article, let's first study the implementation and mounting of React components. 1. What is the component first write the simplest component: after the above code is written, we get the & lt;A / & gt; component, so let's figure out what & lt;A / & gt; is. Print it out with console.log : you can see that & lt;A / & gt; is actually a js object rather than a real DOM. Notice that props is an empty object at this time. Next, let's print & lt;A> , which is component A & lt;/div> , and see what the console outputs: We see that props has changed. Because div and div are nested in the & lt;A / & gt; component, the children attribute is added to the props describing the & lt;A / & gt; object, whose value is the js object describing div . By the same token, if we do multi-level component nesting, we are actually adding children fields and corresponding description values to the props of the parent object, that is, the multi-level nesting of js objects. the above description is based on the React development model of ES6. In fact, the components created by the React.createClass ({}) method in ES5 are exactly the same as those in ES6, and can also…

April 2, 2023 0comments 1619hotness 0likes Aaron Read all

41. If you need to optimize react performance (generally not needed) if both state and props of a component are simple types, you can inherit PureComponent instead of Component import { Component, PureComponent } from 'react'; // bad class Message extends Component { render() { return <span>{this.state.message}</span>; } } // good class Message extends PureComponent { render() { return <span>{this.state.message}</span>; } } override the shouldComponentUpdate method to determine whether re-rendering is needed in shouldComponentUpdate based on whether the state,props has changed. If the component inherits PureComponent, there is no need to override the shouldComponentUpdate method import { isReactPropsEqual, isReactStateEqual } from '@fe/common/lib/equal'; shouldComponentUpdate(nextProps:IProps, nextState:IState) { if (isReactStateEqual(nextState,this.state) && isReactPropsEqual(nextProps,this.props)) { return false; } return true; } 42. Event event object type many friends have used ts for a long time, but they don't know the common Event event object types: ClipboardEvent Clipboard event object DragEvent drag event object ChangeEvent Change event object KeyboardEvent keyboard event object MouseEvent mouse event object TouchEvent Touch event object WheelEvent wheel event object AnimationEvent animated event object TransitionEvent transition event object import { MouseEvent } from 'react'; interface IProps { onClick(event: MouseEvent<HTMLDivElement>): void; } 43. Replace state status with private attributes for some status attributes that do not need to control ui, we can bind them directly to this, that is, private attributes. There is no need to apply them to this.state, otherwise the rendering mechanism will be triggered and performance will be wasted. For example, when we request paging data, we will have a variable. // bad state: IState = { pageNo:1, pageSize:10 };…

March 30, 2023 0comments 1329hotness 0likes Aaron Read all

31. SetState may be synchronous setState is "asynchronous" in compositing events and hook functions in react. setState is synchronized in native events and setTimeout. 32. Do not add await before setState setState can also be preceded by await and become synchronized, but it is a coincidence that we are not sure which version will not support it in the future. In order to follow the design principles of the react framework, we use the form of drop function. // bad func = async (name, value, status) => { await this.setState({ name }); // TODO }; // good func = (name, value, status) => { this.setState( { name }, () => { // TODO } ); }; 33. Block event default behavior you cannot block the default behavior in React by returning false. PreventDefault must be explicitly called. 34. A function that removes side effects in componentWillUnmount clear EventListener abort a data request clear timer 35. key for key optimization in components, maximize reuse of dom //bad this.state.dataAry.map((item, index) => { return <span key={index} />; }); //good this.state.dataAry.map(item => <span key={item.id} />); 36. There must be hasOwnProperty judgment in for-in (that is, it is forbidden to read the properties of prototype objects directly) //bad const arr = []; const key = ''; for (key in obj) { arr.push(obj[key]); } //good const arr = []; const key = ''; for (key in obj) { if (obj.hasOwnProperty(key)) { arr.push(obj[key]); } } 37. The use of third-party library functions wrapped in try catch to prevent errors in the third-party library, causing the whole program…

March 30, 2023 0comments 1332hotness 0likes Aaron Read all

21. Simple components can use functions instead of // bad class Listing extends React.Component { render() { return <div>{this.props.hello}</div>; } } // good function Listing({ hello }) { return <div>{hello}</div>; } 22. Cache commonly used attributes // bad this.props.app.openid; this.state.time // good const { app } = this.props; const { time } = this.state; console.log(app.openid) 23. The input input box uses trim () // bad let searchContent = form.search.value; // good let searchContent = form.search.value.trim(); 24. You need to escape before using location jump // bad window.location.href = redirectUrl + '?a=10&b=20'; // good window.location.href = redirectUrl + encodeURIComponent('?a=10&b=20'); 25. Use react-router // bad import { withRouter, RouteComponentProps } from 'react-router-dom'; export interface IProps extends RouteComponentProps<any> {} class App extends React.Component<IProps, AppStates> {} export default withRouter(App); // good import { withRouter, RouteComponentProps } from 'react-router-dom'; class App extends React.Component<IProps & RouteComponentProps<{}>, AppStates> {} export default withRouter(App); 26. Simultaneous development, data request api directory git conflict directory scheme create a new directory under the api directory. The directory corresponds to the first-level tab, and an index.js is placed in this directory. Finally, all the api requests used by the second-level tab components are introduced into this index.js. // at present |- api |- pageA.ts |- pageB.ts // propose |- api |- pageA |- index.js |- aaa.js |- bbb.js |- pageB |- index.js |- aaa.js |- bbb.js |- ccc.js 27. Components are too deeply nested components generally do not exceed three or four layers at most. Too deep levels may lead to data transfer too deep. When doing some fine-grained operations, it is…

March 30, 2023 0comments 1283hotness 0likes Aaron Read all

11. Type assertion // bad function getLength(something: string | number): number { return something.length; } // index.ts(2,22): error TS2339: Property 'length' does not exist on type 'string | number'. // Property 'length' does not exist on type 'number'. // bad function getLength(something: string | number): number { if ((<string>something).length) { return (<string>something).length; } else { return something.toString().length; } } // good function getLength(something: string | number): number { if (typeof something === 'string') { return something.length; } else { return something.toString().length; } } 12. Interface declaration order there are four kinds of daily use: read-only parameters first, required parameters second, optional parameters second, uncertain parameters last interface iProps { readonly x: number; readonly y: number; name: string; age: number; height?: number; [propName: string]: any; } 13. Ts useful tools generics Record uses this to declare the type of object structure Used to define a javascript object. Key is a string, and value is of any type const people:Record<string,any> = { name: 'chengfeng', age: 10 } Partial is used to make incoming properties optional. interface iPeople { title: string; name: string; } const people: Partial<iPeople> = { title: 'Delete inactive users', }; The defined structure can be any of the interfaces iPeoplekey The function of Readonly is to make the incoming property read-only interface iPeople { title: string; name: string; } const people: Readonly<Todo> = { title: 'todo list', name: chenfeng; }; The title name attribute is read-only The function of Required is to make the passed property a required option interface iPeople { title?: string; name?: string; } const people1:…

March 30, 2023 0comments 1327hotness 0likes Aaron Read all

there is no distinction between right and wrong, and there must be some imperfections, combining my daily development and experience. It allows you to write more rigorous code, and I hope it will be helpful after reading it. 1. Comments (1) comments at the top of the file, including description, author, date /** * @description xxxxxx * @author chengfeng * @since 19/05/21 */ (2) comments on the module /** * Copy Data * @param {*} data Source data to copy * @param {boolean} [isDeep=false] Is it a deep copy? Default is a shallow copy * @return {*} Return copied data */ (3) Business code comments /*Business Code Comment*/ (4) variable comments interface IState { // Name name: string; // Telephone phone: number; // Address address: string; } 2. Reference component order first reference the external component library, then the current component block level component, then the common function library in common, and finally the css style import * as React from 'react'; import { Dropdown, Menu, Icon } from 'antd'; import Header from './Header'; import toast from 'common/toast'; import './index.less'; 3. Quotation marks use single quotes, or backquotes of es6 4. Indent use two spaces const handleCheck = () => { onCancel && onCancel(); onClose && onClose(); }; 5. Semicolon every expression except for a code block must be followed by a semicolon. 6. Parentheses the following keywords must be followed by curly braces (even if the content of the code block is only one line): if, else, for, while, do, switch, try, catch, finally, with. // not good if…

March 30, 2023 0comments 1319hotness 0likes Aaron Read all

case 3: Hooks about time here we mainly introduce three hooks about time: useTimeout , useInterval and useCountDown useTimeout useTimeout : execute once in a period of time pass parameters as long as the function and delay time are needed. It is important to note that when unloading, OK the timer after clearing it detailed code: import { useEffect } from 'react'; import useLatest from '../useLatest'; const useTimeout = (fn:() => void, delay?: number): void => { const fnRef = useLatest(fn) useEffect(() => { if(!delay || delay < 0) return; const timer = setTimeout(() => { fnRef.current(); }, delay) return () => { clearTimeout(timer) } }, [delay]) }; export default useTimeout; useInterval useInterval : execute every time is roughly the same as useTimeout , with an extra parameter of whether to render for the first time immediate detailed code: import { useEffect } from 'react'; import useLatest from '../useLatest'; const useInterval = (fn:() => void, delay?: number, immediate?:boolean): void => { const fnRef = useLatest(fn) useEffect(() => { if(!delay || delay < 0) return; if(immediate) fnRef.current(); const timer = setInterval(() => { fnRef.current(); }, delay) return () => { clearInterval(timer) } }, [delay]) }; export default useInterval; useCountDown useCountDown : hooks that simply control the countdown as before, let's think about what this hook needs: the hook for countdown first needs a target time (targetDate), controls the number of seconds of time change (interval defaults to 1s), and then is the function (onEnd) triggered after the countdown is completed The return parameter of is more clear at a glance. It…

March 30, 2023 0comments 1405hotness 0likes Aaron Read all

case case 1: useReactive useReactive : a useState with responsive reason: we know that variables can be defined in the format with useState const [count, setCount] = useState<number>(0) set it through setCount , and get it by count . Only in this way can the view be rendered Let's take a look at the normal operation, like this let count = 0; count = 7 the value of count is 7, that is to say, the data is responsive so can we also write useState as responsive ? I am free to set the value of count, and I can get the latest value of count at any time, instead of setting it through setCount . Let's think about how to implement a useState with responsive characteristics, that is, useRective If you are interested in the following questions, you can think for yourself first: how to set the import and export parameters of this hook? how to make the data responsive (after all, normal operations can't refresh the view)? how do I use TS to write and refine its type? how to optimize it better? analyze the key of the above four small questions is the second . How do we make the data responsive ? if we want to make it responsive, we must monitor the change of the value and make changes, that is to say, when we operate on this number, we need to intercept intercept . Then we need a knowledge point of ES6 : Proxy the points of Proxy and Reflect will be used here…

March 30, 2023 0comments 1351hotness 0likes Aaron Read all
189101112