Use TS to write React and implement its API
Warehouse address: https://github.com/xuxiaozhou/my-react
How to eat it
git clone https://github.com/xuxiaozhou/my-react
yarn install
yarn build
#Test code directory:./demo
Copy the code
The React family bucket function is implemented
- hook
- lifecycle
- state,props
- event
- Component,PureComponent,FunctionComponent
- react-router
- react-router-dom
- history
- redux
Implementation details
Mount process
- ReactDOM.render(vdom,container)
- Mount using vDOM Mount (vDOM, Container)
- Create a real DOM from vDOM (createDOM)
- Class components
- New generates instance -> Life cycle constructor
- Call getDerivedStateFromProps to get the latest partial state, which is set to the instance
- Call render to get renderVdom -> life cycle render
- RenderVdom is recursively called to createDOM
- Function component
- Call the function component to get the renderVdom
- RenderVdom is recursively called to createDOM
- The HTML element
- Creating a real DOM
- Deal with props
- Recursive children
- Array traversal calls mount
- The mount object calls directly
- Insert the real DOM into the Container -> Life cycle: componentDidMount
- Class components
Event mechanism
The react function handles events, and the life cycle handler is setState in batch update mode, which can be updated once the function completes synchronization
- Bind event handlers (listeners) to the real DOM, which are later retrieved via event.target
- Bind events to document and use dispatchEvent as the handler for all events
- dispatchEvent
- Enter the batch update processing pattern: updateQueue isBatchingUpdate = true
- Create a composite event
- Get the bound event with the current event name recursively up through event.target
- Updatequeue.batchupdate ()
setState
Pre –
- Maintain a global update ue updateQueue
- When a class component performs initialization, it initializes a updater
The real process
- updater.addState
- Determine the current update mode
- Batch update
- Add the current updater to updaters of updateQueue
- Executed immediately
- Perform updater. UpdateClassComponent
- Batch update
- Batch update mode:
- After the event function is processed: updatequeue.batchupdate
- Iterate over all updatequue. Updaters
- Perform updater. UpdateClassComponent
- All updaters are cleared
- Reset to Update now mode
Update mode
- Execute getDerivedStateFromProps to obtain the new partial state
- Set the latest state and props
- Perform shouldComponentUpdate
- Returns false
- Update the end
- Returns true
- Execute Render to get the latest renderVdom
- Perform getSnapshotBeforeUpdate
- The old and new renderVdom performs dom-diff
- Perform componentDidUpdate
- Returns false
Call the forceUpdate component of the class
ShouldComponentUpdate (forceUpdate) shouldComponentUpdate (
- Execute getDerivedStateFromProps to get the latest partial state
- Set the latest state and props
- Execute Render to get the latest renderVdom
- Perform getSnapshotBeforeUpdate
- The old and new renderVdom performs dom-diff
- Perform componentDidUpdate
Unloading phase
- componentWillUnmount
PureComponent and Component
Implement shouldComponentUpdate to make a shallow comparison between the old props and the new state. If they are the same, return true and do not go through the update process. If they are different, return false and go through the update process
export abstract class PureComponent extends Component {
// @ts-ignore
shouldComponentUpdate(nextProps, nextState) {
// true -> Do not update
// false -> Update
return shallowEqual(this.props, nextProps) && shallowEqual(this.state, nextState); }}Copy the code
React.createContext
Mount the context data to the static property _value of the Provider function
function createContext() {
// provide, is a function component
function Provider(props) {
// Keep the object pointer to _value
if(! Provider._value) { Provider._value = props.value || {}; }else {
Object.assign(Provider._value, props.value);
}
return props.children;
}
function Consumer(props) {
props.children(Provider._value);
}
return { Provider, Consumer };
}
Copy the code
Use static contextType = XXX on the class component
On a new class component if the class component has a contextType static method. Provider._value does not change the reference address, so the subsequent values are the latest ones
// react-dom/src/index mountClassComponent
// Perform the assignment
instance.context = Type.contextType.Provider._value
Copy the code
React.memo
Use the react. PureComponent wrapper to compare the old and new props in shouldComponentUpdate
function memo(FunctionComponent) {
return class ClassComponent extends PureComponent {
render() {
return FunctionComponent(this.props); }}; }Copy the code
React.createRef
function createRef() {
return { current: null };
}
Copy the code
Assignment phase
If ref is bound to a DOM element
// react-dom/src/index.ts
// Enter assignment while mounting
if (props.ref) {
props.ref.current = realDOM;
}
Copy the code
If ref is bound to a class component element
// react-dom/src/index.ts mountClassComponent
if (ref) {
ref.current = instance;
}
Copy the code