It has been half a year since I learned React. I have been in touch with hooks and class writing methods of React. Based on this, I would like to write an article to briefly introduce and summarize the original intention of hooks design. The article is divided into three parts:
- Hooks are designed
- Compared with the class
- Ahooks library is introduced
Hooks are designed
There are three main motivations, as stated in the official documentation
1. It is difficult to reuse state logic between components
2. Complex components become difficult to understand
3, difficult to understand the class
The second motivation can be seen as a consequence of the first problem, in that the logic of complex components is confusing and difficult to understand due to the difficulty of logic reuse. Therefore, two motives can be simplified and explained one by one
· Logic reuse
There are two ways to reuse traditional class component logic: high-level components, render props, and mixins. Mixins are not recommended because of naming conflicts and implicit dependencies. Take the example of a table request.Implement a table component, divided into two parts, one is the logic, the other part is the view (render function). The logical section is roughly divided into the following concerns
Loading asynchronous loading 2, pageSize 3, pageSize 4, Filter criteria when switching, to reset the page to the first page. 5. When the component is uninstalled, clear the network requests that are in progress.
If only the rendering function of the table component is reused (i.e. the table is a purely functional component with no lifecycle), then the lifecycle function, the logical processing part, must be rewritten each time in the class component that references the table. If you put the lifecycle part of the table component, it becomes difficult to add your own logic to the general logic. In this case, the table is a complete component, and you can inject additional content into the table component using methods such as render props, which adds complexity. Hooks are a better way to reuse logic.
const { tableProps, search, params } = useAntdTable(getTableData, { defaultPageSize: 5, form, }); // <Table columns={columns} {... tableProps} />Copy the code
The hooks themselves are like arguments that can be passed to components and reused for the class’s lifecycle. This is even clearer if you use hooks to simulate inheritance.
However, hooks cannot completely replace the higher-order components, render props, and need to be considered in a case-by-case manner.
· Unintelligible class
Class is hard to understand because this is complicated. Beyond the traditional this problem, Dan Abramov writes that the difference between functional components and class components is at the heart of the problem.
There are now two components:
class ProfilePage extends React.Component {
showMessage = () = > {
alert('Followed ' + this.props.user);
};
handleClick = () = > {
setTimeout(this.showMessage, 3000);
};
render() {
return <button onClick={this.handleClick}>Follow</button>; }}Copy the code
function ProfilePage(props) {
const showMessage = () = > {
alert('Followed ' + props.user);
};
const handleClick = () = > {
setTimeout(showMessage, 3000);
};
return (
<button onClick={handleClick}>Follow</button>
);
}
Copy the code
The above two components have the same function, and the concerned user is printed after 3s. One is a class component and one is a functional component. If the props changes in 3s, the user of the class component changes, but the functional component does not. This is not about old and new data, but the component should not confuse the actual user, which can be a problem in some cases. You should not arbitrarily change A into B after you focus on A. If you rewrite a class component, you get the same result as a functional component.
class ProfilePage extends React.Component {
render() {
const props = this.props;
const showMessage = () = > {
alert('Followed ' + props.user);
};
const handleClick = () = > {
setTimeout(showMessage, 3000);
};
return <button onClick={handleClick}>Follow</button>; }}Copy the code
The result of a class component is the same as a functional component. If you look further, the Render function is the function component from which the hooks are hidden.
Comparing the two components leads to the conclusion
1. Functional components capture the values used for rendering
2. This will always change
Capturing the values used for rendering makes use of closures. Closures are functions that can read variables inside other functions. A common throttling and anti-shake principle is closures, which can also be used as private properties.
Comparison with class components
Here do not list the specific differences above the development, these online also have a lot of information, mainly lists the similarities and differences of the foundation and development ideas comparison. The main reference here is the official documentation.
GetSnapshotBeforeUpdate, componentDidCatch and getDerivedStateFromError will add hooks as soon as possible.
2. Any function inside a component, including event handlers and effects, is “seen” from the render in which it was created. This is actually a closure, and a common problem in development is outdated closures.
3, class component object-oriented programming thought, can obtain the maximum degree of operation authority, all attributes of the object can be controlled. Can facilitate invasive operations.
4. Functional components are like procedural programming, handling modules as functions, which have some object-oriented characteristics thanks to hooks that enable functions to have side effects. In addition, functional expressions can be seamlessly transformed into logical flows. Flow control comes naturally to mind.
Logic reuse, hooks and mixin. A mixin can be thought of as a class that every component mixed with it has and can be overridden, equivalent to inheritance. Hooks Pure function logic, treated as a parameter.
Introduction of ahooks
Ahooks is an open source hooks library that contains a number of hooks that are frequently used.
function useCreation(factory, deps) {
var current = react_1.useRef({
deps: deps,
obj: undefined.initialized: false
}).current;
if (current.initialized === false| |! depsAreSame(current.deps, deps)) { current.deps = deps; current.obj = factory(); current.initialized =true;
}
return current.obj;
}
Copy the code
To prevent repeated instances from being created, use useRef as a flag and store it as a singleton.
var useDeepCompareEffect = function useDeepCompareEffect(effect, deps) {
var ref = react_1.useRef();
var signalRef = react_1.useRef(0);
if(! depsEqual(deps, ref.current)) { ref.current = deps; signalRef.current +=1;
}
react_1.useEffect(effect, [signalRef.current]);
};
Copy the code
Deep comparison of useEffect dependencies, new hooks in version 3.0, more useful. Use useRef to store updates
var useSetState = function useSetState(initialState) {
var _a = __read(react_1.useState(initialState), 2),
state = _a[0],
setState = _a[1];
var setMergeState = react_1.useCallback(function (patch) {
setState(function (prevState) {
var newState = utils_1.isFunction(patch) ? patch(prevState) : patch;
returnnewState ? __assign(__assign({}, prevState), newState) : prevState; }); } []);return [state, setMergeState];
};
Copy the code
Automatically merge state. SetState is not merged by default. It is also important to use setState wisely here, as putting all the states together sometimes does not help to pull out the state and encapsulate hooks.
function useMemoizedFn(fn) {...var fnRef = react_1.useRef(fn);
fnRef.current = react_1.useMemo(function () {
return fn;
}, [fn]);
var memoizedFn = react_1.useRef();
if(! memoizedFn.current) { memoizedFn.current =function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
return fnRef.current.apply(this, args);
};
}
return memoizedFn.current;
}
Copy the code
Replace useCallBack, avoid useCallBack re-rendering, performance optimization. Use ref.current to avoid causing update notifications
Four,
This is a basic introduction to hooks, which can be learned from the hooks website. For an in-depth understanding of hooks’ design, check out Dan Abramov’s blog, which delves into the philosophy of hooks. Ahooks are not magic at heart, nothing deep, but cleverly designed and worth learning from. In future thinking we will focus on hooks and class update rendering.
Learn more about the hooks principle and react source code in the following article 🙂
Reference links:
react.docschina.org/
zhuanlan.zhihu.com/p/104126843
Ahooks. Gitee. IO/useful – CN/hooks…
Overreacted. IO/useful – Hans/a – c…
React.docschina.org/blog/2016/0…